diff options
Diffstat (limited to 'src/gui/painting')
30 files changed, 598 insertions, 2664 deletions
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 94a88f55dc..21a40540c4 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -26,7 +26,6 @@ HEADERS += \ painting/qfixed_p.h \ painting/qgrayraster_p.h \ painting/qicc_p.h \ - painting/qmatrix.h \ painting/qmemrotate_p.h \ painting/qoutlinemapper_p.h \ painting/qpagedpaintdevice.h \ @@ -83,7 +82,6 @@ SOURCES += \ painting/qgrayraster.c \ painting/qicc.cpp \ painting/qimagescale.cpp \ - painting/qmatrix.cpp \ painting/qmemrotate.cpp \ painting/qoutlinemapper.cpp \ painting/qpagedpaintdevice.cpp \ diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 2147d9d61d..5bbc03db80 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -322,7 +322,7 @@ void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPo // make sure we don't detach uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits()); - int lineskip = img.bytesPerLine(); + qsizetype lineskip = img.bytesPerLine(); int depth = img.depth() >> 3; const QRect imageRect(0, 0, img.width(), img.height()); diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 28cc20bfc5..c8fc447446 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -892,26 +892,6 @@ bool QBrush::isOpaque() const return false; } - -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \since 4.2 - \obsolete - - Use setTransform() instead. - - Sets \a matrix as an explicit transformation matrix on the - current brush. The brush transformation matrix is merged with - QPainter transformation matrix to produce the final result. - - \sa matrix() -*/ -void QBrush::setMatrix(const QMatrix &matrix) -{ - setTransform(QTransform(matrix)); -} -#endif // QT_DEPRECATED_SINCE(5, 15) - /*! \since 4.3 diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 3a01248c57..621387615b 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -46,7 +46,6 @@ #include <QtCore/qvector.h> #include <QtCore/qscopedpointer.h> #include <QtGui/qcolor.h> -#include <QtGui/qmatrix.h> #include <QtGui/qtransform.h> #include <QtGui/qimage.h> #include <QtGui/qpixmap.h> @@ -89,11 +88,6 @@ public: inline Qt::BrushStyle style() const; void setStyle(Qt::BrushStyle); -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use transform()") inline const QMatrix &matrix() const; - QT_DEPRECATED_X("Use setTransform()") void setMatrix(const QMatrix &mat); -#endif // QT_DEPRECATED_SINCE(5, 15) - inline QTransform transform() const; void setTransform(const QTransform &); @@ -159,10 +153,6 @@ struct QBrushData inline Qt::BrushStyle QBrush::style() const { return d->style; } inline const QColor &QBrush::color() const { return d->color; } -#if QT_DEPRECATED_SINCE(5, 15) -QT_DEPRECATED_X("Use transform()") -inline const QMatrix &QBrush::matrix() const { return d->transform.toAffine(); } -#endif // QT_DEPRECATED_SINCE(5, 15) inline QTransform QBrush::transform() const { return d->transform; } inline bool QBrush::isDetached() const { return d->ref.loadRelaxed() == 1; } diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index f15f6aeebd..eac2a50c8c 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -855,18 +855,6 @@ QColor::QColor(Spec spec) noexcept */ /*! - Returns the name of the color in the format "#RRGGBB"; i.e. a "#" - character followed by three two-digit hexadecimal numbers. - - \sa setNamedColor() -*/ - -QString QColor::name() const -{ - return name(HexRgb); -} - -/*! \since 5.2 Returns the name of the color in the specified \a format. @@ -1086,6 +1074,7 @@ void QColor::setHsvF(qreal h, qreal s, qreal v, qreal a) || (v < qreal(0.0) || v > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { qWarning("QColor::setHsvF: HSV parameters out of range"); + invalidate(); return; } @@ -1198,7 +1187,8 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) || (s < qreal(0.0) || s > qreal(1.0)) || (l < qreal(0.0) || l > qreal(1.0)) || (a < qreal(0.0) || a > qreal(1.0))) { - qWarning("QColor::setHsvF: HSV parameters out of range"); + qWarning("QColor::setHslF: HSL parameters out of range"); + invalidate(); return; } @@ -1224,7 +1214,7 @@ void QColor::setHslF(qreal h, qreal s, qreal l, qreal a) void QColor::setHsl(int h, int s, int l, int a) { if (h < -1 || (uint)s > 255 || (uint)l > 255 || (uint)a > 255) { - qWarning("QColor::setHsv: HSV parameters out of range"); + qWarning("QColor::setHsl: HSL parameters out of range"); invalidate(); return; } @@ -2626,16 +2616,6 @@ QColor QColor::fromHslF(qreal h, qreal s, qreal l, qreal a) } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) -{ - const_cast<const QColor *>(this)->getCmyk(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2665,16 +2645,6 @@ void QColor::getCmyk(int *c, int *m, int *y, int *k, int *a) const } /*! - \obsolete - - Use the \c const overload instead. -*/ -void QColor::getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a) -{ - const_cast<const QColor *>(this)->getCmykF(c, m, y, k, a); -} - -/*! Sets the contents pointed to by \a c, \a m, \a y, \a k, and \a a, to the cyan, magenta, yellow, black, and alpha-channel (transparency) components of the color's CMYK value. @@ -2719,6 +2689,7 @@ void QColor::setCmyk(int c, int m, int y, int k, int a) || k < 0 || k > 255 || a < 0 || a > 255) { qWarning("QColor::setCmyk: CMYK parameters out of range"); + invalidate(); return; } @@ -2748,6 +2719,7 @@ void QColor::setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a) || k < qreal(0.0) || k > qreal(1.0) || a < qreal(0.0) || a > qreal(1.0)) { qWarning("QColor::setCmykF: CMYK parameters out of range"); + invalidate(); return; } @@ -2920,18 +2892,6 @@ QColor QColor::dark(int factor) const noexcept } #endif -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) -/*! - Assigns a copy of \a color to this color, and returns a reference to it. -*/ -QColor &QColor::operator=(const QColor &color) noexcept -{ - cspec = color.cspec; - ct.argb = color.ct.argb; - return *this; -} -#endif - /*! \overload Assigns a copy of \a color and returns a reference to this color. */ diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h index 0189f4e5f1..ad624e6b60 100644 --- a/src/gui/painting/qcolor.h +++ b/src/gui/painting/qcolor.h @@ -46,6 +46,8 @@ #include <QtCore/qstringlist.h> #include <QtGui/qrgba64.h> +#include <limits.h> + QT_BEGIN_NAMESPACE @@ -87,24 +89,11 @@ public: inline QColor(QLatin1String name); QColor(Spec spec) noexcept; -#if QT_VERSION < QT_VERSION_CHECK(6,0,0) - // ### Qt 6: remove all of these, the trivial ones are fine. - Q_DECL_CONSTEXPR QColor(const QColor &color) noexcept - : cspec(color.cspec), ct(color.ct) - {} - Q_DECL_CONSTEXPR QColor(QColor &&other) noexcept : cspec(other.cspec), ct(other.ct) {} - QColor &operator=(QColor &&other) noexcept - { cspec = other.cspec; ct = other.ct; return *this; } - QColor &operator=(const QColor &) noexcept; -#endif // Qt < 6 - QColor &operator=(Qt::GlobalColor color) noexcept; bool isValid() const noexcept; - // ### Qt 6: merge overloads - QString name() const; - QString name(NameFormat format) const; + QString name(NameFormat format = HexRgb) const; #if QT_STRINGVIEW_LEVEL < 2 void setNamedColor(const QString& name); @@ -180,11 +169,9 @@ public: qreal yellowF() const noexcept; qreal blackF() const noexcept; - void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr); // ### Qt 6: remove void getCmyk(int *c, int *m, int *y, int *k, int *a = nullptr) const; void setCmyk(int c, int m, int y, int k, int a = 255); - void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr); // ### Qt 6: remove void getCmykF(qreal *c, qreal *m, qreal *y, qreal *k, qreal *a = nullptr) const; void setCmykF(qreal c, qreal m, qreal y, qreal k, qreal a = 1.0); diff --git a/src/gui/painting/qcolormatrix_p.h b/src/gui/painting/qcolormatrix_p.h index edb2d32258..749aad3b2c 100644 --- a/src/gui/painting/qcolormatrix_p.h +++ b/src/gui/painting/qcolormatrix_p.h @@ -112,7 +112,7 @@ inline bool operator!=(const QColorVector &v1, const QColorVector &v2) // A matrix mapping 3 value colors. -// Not using QMatrix because only floats are needed and performance is critical. +// Not using QTransform because only floats are needed and performance is critical. class QColorMatrix { public: diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h index 181d19da0b..676750b716 100644 --- a/src/gui/painting/qdatabuffer_p.h +++ b/src/gui/painting/qdatabuffer_p.h @@ -116,7 +116,7 @@ public: capacity = 1; while (capacity < size) capacity *= 2; - buffer = (Type*) realloc(buffer, capacity * sizeof(Type)); + buffer = (Type*) realloc(static_cast<void*>(buffer), capacity * sizeof(Type)); Q_CHECK_PTR(buffer); } } @@ -124,7 +124,7 @@ public: inline void shrink(int size) { capacity = size; if (size) { - buffer = (Type*) realloc(buffer, capacity * sizeof(Type)); + buffer = (Type*) realloc(static_cast<void*>(buffer), capacity * sizeof(Type)); Q_CHECK_PTR(buffer); } else { free(buffer); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 2d4045fe29..e4e8305620 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2906,7 +2906,7 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint int32x4_t v_fdy = vdupq_n_s32(fdy * 4); const uchar *textureData = image.imageData; - const int bytesPerLine = image.bytesPerLine; + const qsizetype bytesPerLine = image.bytesPerLine; int32x4_t v_fx = vmovq_n_s32(fx); int32x4_t v_fy = vmovq_n_s32(fy); diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp index 14d7047bb6..a175b591dd 100644 --- a/src/gui/painting/qdrawhelper_ssse3.cpp +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -197,7 +197,7 @@ void qt_memfill24_ssse3(quint24 *dest, quint24 color, qsizetype count) quint24 *end = dest + count; constexpr uchar x = 2, y = 1, z = 0; - Q_DECL_ALIGN(__m128i) static const uchar + alignas(__m128i) static const uchar shuffleMask[16 + 1] = { x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y }; __m128i mval1 = _mm_shuffle_epi8(m, _mm_load_si128(reinterpret_cast<const __m128i *>(shuffleMask))); diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp deleted file mode 100644 index 7ebd2dbd09..0000000000 --- a/src/gui/painting/qmatrix.cpp +++ /dev/null @@ -1,1191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui 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 "qmatrix.h" - -#include "qdatastream.h" -#include "qdebug.h" -#include "qhashfunctions.h" -#include "qregion.h" -#include "qpainterpath.h" -#include "qpainterpath_p.h" -#include "qtransform.h" -#include "qvariant.h" -#include <qmath.h> - -#include <limits.h> - -QT_BEGIN_NAMESPACE - -/*! - \class QMatrix - \brief The QMatrix class specifies 2D transformations of a - coordinate system. - \obsolete - - \ingroup painting - \inmodule QtGui - - A matrix specifies how to translate, scale, shear or rotate the - coordinate system, and is typically used when rendering graphics. - QMatrix, in contrast to QTransform, does not allow perspective - transformations. QTransform is the recommended transformation - class in Qt. - - A QMatrix object can be built using the setMatrix(), scale(), - rotate(), translate() and shear() functions. Alternatively, it - can be built by applying \l {QMatrix#Basic Matrix - Operations}{basic matrix operations}. The matrix can also be - defined when constructed, and it can be reset to the identity - matrix (the default) using the reset() function. - - The QMatrix class supports mapping of graphic primitives: A given - point, line, polygon, region, or painter path can be mapped to the - coordinate system defined by \e this matrix using the map() - function. In case of a rectangle, its coordinates can be - transformed using the mapRect() function. A rectangle can also be - transformed into a \e polygon (mapped to the coordinate system - defined by \e this matrix), using the mapToPolygon() function. - - QMatrix provides the isIdentity() function which returns \c true if - the matrix is the identity matrix, and the isInvertible() function - which returns \c true if the matrix is non-singular (i.e. AB = BA = - I). The inverted() function returns an inverted copy of \e this - matrix if it is invertible (otherwise it returns the identity - matrix). In addition, QMatrix provides the determinant() function - returning the matrix's determinant. - - Finally, the QMatrix class supports matrix multiplication, and - objects of the class can be streamed as well as compared. - - \tableofcontents - - \section1 Rendering Graphics - - When rendering graphics, the matrix defines the transformations - but the actual transformation is performed by the drawing routines - in QPainter. - - By default, QPainter operates on the associated device's own - coordinate system. The standard coordinate system of a - QPaintDevice has its origin located at the top-left position. The - \e x values increase to the right; \e y values increase - downward. For a complete description, see the \l {Coordinate - System}{coordinate system} documentation. - - QPainter has functions to translate, scale, shear and rotate the - coordinate system without using a QMatrix. For example: - - \table 100% - \row - \li \inlineimage qmatrix-simpletransformation.png - \li - \snippet matrix/matrix.cpp 0 - \endtable - - Although these functions are very convenient, it can be more - efficient to build a QMatrix and call QPainter::setMatrix() if you - want to perform more than a single transform operation. For - example: - - \table 100% - \row - \li \inlineimage qmatrix-combinedtransformation.png - \li - \snippet matrix/matrix.cpp 1 - \endtable - - \section1 Basic Matrix Operations - - \image qmatrix-representation.png - - A QMatrix object contains a 3 x 3 matrix. The \c dx and \c dy - elements specify horizontal and vertical translation. The \c m11 - and \c m22 elements specify horizontal and vertical scaling. And - finally, the \c m21 and \c m12 elements specify horizontal and - vertical \e shearing. - - QMatrix transforms a point in the plane to another point using the - following formulas: - - \snippet code/src_gui_painting_qmatrix.cpp 0 - - The point \e (x, y) is the original point, and \e (x', y') is the - transformed point. \e (x', y') can be transformed back to \e (x, - y) by performing the same operation on the inverted() matrix. - - The various matrix elements can be set when constructing the - matrix, or by using the setMatrix() function later on. They can also - be manipulated using the translate(), rotate(), scale() and - shear() convenience functions, The currently set values can be - retrieved using the m11(), m12(), m21(), m22(), dx() and dy() - functions. - - Translation is the simplest transformation. Setting \c dx and \c - dy will move the coordinate system \c dx units along the X axis - and \c dy units along the Y axis. Scaling can be done by setting - \c m11 and \c m22. For example, setting \c m11 to 2 and \c m22 to - 1.5 will double the height and increase the width by 50%. The - identity matrix has \c m11 and \c m22 set to 1 (all others are set - to 0) mapping a point to itself. Shearing is controlled by \c m12 - and \c m21. Setting these elements to values different from zero - will twist the coordinate system. Rotation is achieved by - carefully setting both the shearing factors and the scaling - factors. - - Here's the combined transformations example using basic matrix - operations: - - \table 100% - \row - \li \inlineimage qmatrix-combinedtransformation.png - \li - \snippet matrix/matrix.cpp 2 - \endtable - - \sa QPainter, QTransform, {Coordinate System}, - {painting/affine}{Affine Transformations Example}, {Transformations Example} -*/ - - -// some defines to inline some code -#define MAPDOUBLE(x, y, nx, ny) \ -{ \ - qreal fx = x; \ - qreal fy = y; \ - nx = _m11*fx + _m21*fy + _dx; \ - ny = _m12*fx + _m22*fy + _dy; \ -} - -#define MAPINT(x, y, nx, ny) \ -{ \ - qreal fx = x; \ - qreal fy = y; \ - nx = qRound(_m11*fx + _m21*fy + _dx); \ - ny = qRound(_m12*fx + _m22*fy + _dy); \ -} - -/***************************************************************************** - QMatrix member functions - *****************************************************************************/ -/*! - \fn QMatrix::QMatrix(Qt::Initialization) - \internal -*/ - -/*! - Constructs an identity matrix. - - All elements are set to zero except \c m11 and \c m22 (specifying - the scale), which are set to 1. - - \sa reset() -*/ - -QMatrix::QMatrix() - : _m11(1.) - , _m12(0.) - , _m21(0.) - , _m22(1.) - , _dx(0.) - , _dy(0.) -{ -} - -/*! - Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a - m22, \a dx and \a dy. - - \sa setMatrix() -*/ - -QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) - : _m11(m11) - , _m12(m12) - , _m21(m21) - , _m22(m22) - , _dx(dx) - , _dy(dy) -{ -} - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -/*! - Constructs a matrix that is a copy of the given \a matrix. - */ -QMatrix::QMatrix(const QMatrix &matrix) noexcept - : _m11(matrix._m11) - , _m12(matrix._m12) - , _m21(matrix._m21) - , _m22(matrix._m22) - , _dx(matrix._dx) - , _dy(matrix._dy) -{ -} -#endif - -/*! - Sets the matrix elements to the specified values, \a m11, \a m12, - \a m21, \a m22, \a dx and \a dy. - - Note that this function replaces the previous values. QMatrix - provide the translate(), rotate(), scale() and shear() convenience - functions to manipulate the various matrix elements based on the - currently defined coordinate system. - - \sa QMatrix() -*/ - -void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) -{ - _m11 = m11; - _m12 = m12; - _m21 = m21; - _m22 = m22; - _dx = dx; - _dy = dy; -} - - -/*! - \fn qreal QMatrix::m11() const - - Returns the horizontal scaling factor. - - \sa scale(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - -/*! - \fn qreal QMatrix::m12() const - - Returns the vertical shearing factor. - - \sa shear(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - -/*! - \fn qreal QMatrix::m21() const - - Returns the horizontal shearing factor. - - \sa shear(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - -/*! - \fn qreal QMatrix::m22() const - - Returns the vertical scaling factor. - - \sa scale(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - -/*! - \fn qreal QMatrix::dx() const - - Returns the horizontal translation factor. - - \sa translate(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - -/*! - \fn qreal QMatrix::dy() const - - Returns the vertical translation factor. - - \sa translate(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ - - -/*! - Maps the given coordinates \a x and \a y into the coordinate - system defined by this matrix. The resulting values are put in *\a - tx and *\a ty, respectively. - - The coordinates are transformed using the following formulas: - - \snippet code/src_gui_painting_qmatrix.cpp 1 - - The point (x, y) is the original point, and (x', y') is the - transformed point. - - \sa {QMatrix#Basic Matrix Operations}{Basic Matrix Operations} -*/ - -void QMatrix::map(qreal x, qreal y, qreal *tx, qreal *ty) const -{ - MAPDOUBLE(x, y, *tx, *ty); -} - - - -/*! - \overload - - Maps the given coordinates \a x and \a y into the coordinate - system defined by this matrix. The resulting values are put in *\a - tx and *\a ty, respectively. Note that the transformed coordinates - are rounded to the nearest integer. -*/ - -void QMatrix::map(int x, int y, int *tx, int *ty) const -{ - MAPINT(x, y, *tx, *ty); -} - -QRect QMatrix::mapRect(const QRect &rect) const -{ - QRect result; - if (_m12 == 0.0F && _m21 == 0.0F) { - int x = qRound(_m11*rect.x() + _dx); - int y = qRound(_m22*rect.y() + _dy); - int w = qRound(_m11*rect.width()); - int h = qRound(_m22*rect.height()); - if (w < 0) { - w = -w; - x -= w; - } - if (h < 0) { - h = -h; - y -= h; - } - result = QRect(x, y, w, h); - } else { - // see mapToPolygon for explanations of the algorithm. - qreal x0, y0; - qreal x, y; - MAPDOUBLE(rect.left(), rect.top(), x0, y0); - qreal xmin = x0; - qreal ymin = y0; - qreal xmax = x0; - qreal ymax = y0; - MAPDOUBLE(rect.right() + 1, rect.top(), x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - MAPDOUBLE(rect.right() + 1, rect.bottom() + 1, x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - MAPDOUBLE(rect.left(), rect.bottom() + 1, x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - result = QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin)); - } - return result; -} - -/*! - \fn QRectF QMatrix::mapRect(const QRectF &rectangle) const - - Creates and returns a QRectF object that is a copy of the given \a - rectangle, mapped into the coordinate system defined by this - matrix. - - The rectangle's coordinates are transformed using the following - formulas: - - \snippet code/src_gui_painting_qmatrix.cpp 2 - - If rotation or shearing has been specified, this function returns - the \e bounding rectangle. To retrieve the exact region the given - \a rectangle maps to, use the mapToPolygon() function instead. - - \sa mapToPolygon(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ -QRectF QMatrix::mapRect(const QRectF &rect) const -{ - QRectF result; - if (_m12 == 0.0F && _m21 == 0.0F) { - qreal x = _m11*rect.x() + _dx; - qreal y = _m22*rect.y() + _dy; - qreal w = _m11*rect.width(); - qreal h = _m22*rect.height(); - if (w < 0) { - w = -w; - x -= w; - } - if (h < 0) { - h = -h; - y -= h; - } - result = QRectF(x, y, w, h); - } else { - qreal x0, y0; - qreal x, y; - MAPDOUBLE(rect.x(), rect.y(), x0, y0); - qreal xmin = x0; - qreal ymin = y0; - qreal xmax = x0; - qreal ymax = y0; - MAPDOUBLE(rect.x() + rect.width(), rect.y(), x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - MAPDOUBLE(rect.x() + rect.width(), rect.y() + rect.height(), x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - MAPDOUBLE(rect.x(), rect.y() + rect.height(), x, y); - xmin = qMin(xmin, x); - ymin = qMin(ymin, y); - xmax = qMax(xmax, x); - ymax = qMax(ymax, y); - result = QRectF(xmin, ymin, xmax-xmin, ymax - ymin); - } - return result; -} - -/*! - \fn QRect QMatrix::mapRect(const QRect &rectangle) const - \overload - - Creates and returns a QRect object that is a copy of the given \a - rectangle, mapped into the coordinate system defined by this - matrix. Note that the transformed coordinates are rounded to the - nearest integer. -*/ - - -/*! - \fn QPoint operator*(const QPoint &point, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{point}). - - \sa QMatrix::map() -*/ - -QPoint QMatrix::map(const QPoint &p) const -{ - qreal fx = p.x(); - qreal fy = p.y(); - return QPoint(qRound(_m11*fx + _m21*fy + _dx), - qRound(_m12*fx + _m22*fy + _dy)); -} - -/*! - \fn QPointF operator*(const QPointF &point, const QMatrix &matrix) - \relates QMatrix - - Same as \a{matrix}.map(\a{point}). - - \sa QMatrix::map() -*/ - -/*! - \overload - - Creates and returns a QPointF object that is a copy of the given - \a point, mapped into the coordinate system defined by this - matrix. -*/ -QPointF QMatrix::map(const QPointF &point) const -{ - qreal fx = point.x(); - qreal fy = point.y(); - return QPointF(_m11*fx + _m21*fy + _dx, _m12*fx + _m22*fy + _dy); -} - -/*! - \fn QPoint QMatrix::map(const QPoint &point) const - \overload - - Creates and returns a QPoint object that is a copy of the given \a - point, mapped into the coordinate system defined by this - matrix. Note that the transformed coordinates are rounded to the - nearest integer. -*/ - -/*! - \fn QLineF operator*(const QLineF &line, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{line}). - - \sa QMatrix::map() -*/ - -/*! - \fn QLine operator*(const QLine &line, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{line}). - - \sa QMatrix::map() -*/ - -/*! - \overload - - Creates and returns a QLineF object that is a copy of the given \a - line, mapped into the coordinate system defined by this matrix. -*/ -QLineF QMatrix::map(const QLineF &line) const -{ - return QLineF(map(line.p1()), map(line.p2())); -} - -/*! - \overload - - Creates and returns a QLine object that is a copy of the given \a - line, mapped into the coordinate system defined by this matrix. - Note that the transformed coordinates are rounded to the nearest - integer. -*/ -QLine QMatrix::map(const QLine &line) const -{ - return QLine(map(line.p1()), map(line.p2())); -} - -/*! - \fn QPolygonF operator *(const QPolygonF &polygon, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{polygon}). - - \sa QMatrix::map() -*/ - -/*! - \fn QPolygon operator*(const QPolygon &polygon, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{polygon}). - - \sa QMatrix::map() -*/ - -QPolygon QMatrix::map(const QPolygon &a) const -{ - int size = a.size(); - int i; - QPolygon p(size); - const QPoint *da = a.constData(); - QPoint *dp = p.data(); - for(i = 0; i < size; i++) { - MAPINT(da[i].x(), da[i].y(), dp[i].rx(), dp[i].ry()); - } - return p; -} - -/*! - \fn QPolygonF QMatrix::map(const QPolygonF &polygon) const - \overload - - Creates and returns a QPolygonF object that is a copy of the given - \a polygon, mapped into the coordinate system defined by this - matrix. -*/ -QPolygonF QMatrix::map(const QPolygonF &a) const -{ - int size = a.size(); - int i; - QPolygonF p(size); - const QPointF *da = a.constData(); - QPointF *dp = p.data(); - for(i = 0; i < size; i++) { - MAPDOUBLE(da[i].xp, da[i].yp, dp[i].xp, dp[i].yp); - } - return p; -} - -/*! - \fn QPolygon QMatrix::map(const QPolygon &polygon) const - \overload - - Creates and returns a QPolygon object that is a copy of the given - \a polygon, mapped into the coordinate system defined by this - matrix. Note that the transformed coordinates are rounded to the - nearest integer. -*/ - -/*! - \fn QRegion operator*(const QRegion ®ion, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{region}). - - \sa QMatrix::map() -*/ - -extern QPainterPath qt_regionToPath(const QRegion ®ion); - -/*! - \fn QRegion QMatrix::map(const QRegion ®ion) const - \overload - - Creates and returns a QRegion object that is a copy of the given - \a region, mapped into the coordinate system defined by this matrix. - - Calling this method can be rather expensive if rotations or - shearing are used. -*/ -QRegion QMatrix::map(const QRegion &r) const -{ - if (_m11 == 1.0 && _m22 == 1.0 && _m12 == 0.0 && _m21 == 0.0) { // translate or identity - if (_dx == 0.0 && _dy == 0.0) // Identity - return r; - QRegion copy(r); - copy.translate(qRound(_dx), qRound(_dy)); - return copy; - } - - QPainterPath p = map(qt_regionToPath(r)); - return p.toFillPolygon(QTransform()).toPolygon(); -} - -/*! - \fn QPainterPath operator *(const QPainterPath &path, const QMatrix &matrix) - \relates QMatrix - - This is the same as \a{matrix}.map(\a{path}). - - \sa QMatrix::map() -*/ - -/*! - \overload - - Creates and returns a QPainterPath object that is a copy of the - given \a path, mapped into the coordinate system defined by this - matrix. -*/ -QPainterPath QMatrix::map(const QPainterPath &path) const -{ - if (path.isEmpty()) - return QPainterPath(); - - QPainterPath copy = path; - - // Translate or identity - if (_m11 == 1.0 && _m22 == 1.0 && _m12 == 0.0 && _m21 == 0.0) { - - // Translate - if (_dx != 0.0 || _dy != 0.0) { - copy.detach(); - for (int i=0; i<path.elementCount(); ++i) { - QPainterPath::Element &e = copy.d_ptr->elements[i]; - e.x += _dx; - e.y += _dy; - } - } - - // Full xform - } else { - copy.detach(); - for (int i=0; i<path.elementCount(); ++i) { - QPainterPath::Element &e = copy.d_ptr->elements[i]; - qreal fx = e.x, fy = e.y; - e.x = _m11*fx + _m21*fy + _dx; - e.y = _m12*fx + _m22*fy + _dy; - } - } - - return copy; -} - -/*! - \fn QPolygon QMatrix::mapToPolygon(const QRect &rectangle) const - - Creates and returns a QPolygon representation of the given \a - rectangle, mapped into the coordinate system defined by this - matrix. - - The rectangle's coordinates are transformed using the following - formulas: - - \snippet code/src_gui_painting_qmatrix.cpp 3 - - Polygons and rectangles behave slightly differently when - transformed (due to integer rounding), so - \c{matrix.map(QPolygon(rectangle))} is not always the same as - \c{matrix.mapToPolygon(rectangle)}. - - \sa mapRect(), {QMatrix#Basic Matrix Operations}{Basic Matrix - Operations} -*/ -QPolygon QMatrix::mapToPolygon(const QRect &rect) const -{ - QPolygon a(4); - qreal x[4], y[4]; - if (_m12 == 0.0F && _m21 == 0.0F) { - x[0] = _m11*rect.x() + _dx; - y[0] = _m22*rect.y() + _dy; - qreal w = _m11*rect.width(); - qreal h = _m22*rect.height(); - if (w < 0) { - w = -w; - x[0] -= w; - } - if (h < 0) { - h = -h; - y[0] -= h; - } - x[1] = x[0]+w; - x[2] = x[1]; - x[3] = x[0]; - y[1] = y[0]; - y[2] = y[0]+h; - y[3] = y[2]; - } else { - qreal right = rect.x() + rect.width(); - qreal bottom = rect.y() + rect.height(); - MAPDOUBLE(rect.x(), rect.y(), x[0], y[0]); - MAPDOUBLE(right, rect.y(), x[1], y[1]); - MAPDOUBLE(right, bottom, x[2], y[2]); - MAPDOUBLE(rect.x(), bottom, x[3], y[3]); - } -#if 0 - int i; - for(i = 0; i< 4; i++) - qDebug("coords(%d) = (%f/%f) (%d/%d)", i, x[i], y[i], qRound(x[i]), qRound(y[i])); - qDebug("width=%f, height=%f", qSqrt((x[1]-x[0])*(x[1]-x[0]) + (y[1]-y[0])*(y[1]-y[0])), - qSqrt((x[0]-x[3])*(x[0]-x[3]) + (y[0]-y[3])*(y[0]-y[3]))); -#endif - // all coordinates are correctly, tranform to a pointarray - // (rounding to the next integer) - a.setPoints(4, qRound(x[0]), qRound(y[0]), - qRound(x[1]), qRound(y[1]), - qRound(x[2]), qRound(y[2]), - qRound(x[3]), qRound(y[3])); - return a; -} - -/*! - Resets the matrix to an identity matrix, i.e. all elements are set - to zero, except \c m11 and \c m22 (specifying the scale) which are - set to 1. - - \sa QMatrix(), isIdentity(), {QMatrix#Basic Matrix - Operations}{Basic Matrix Operations} -*/ - -void QMatrix::reset() -{ - _m11 = _m22 = 1.0; - _m12 = _m21 = _dx = _dy = 0.0; -} - -/*! - \fn bool QMatrix::isIdentity() const - - Returns \c true if the matrix is the identity matrix, otherwise - returns \c false. - - \sa reset() -*/ - -/*! - Moves the coordinate system \a dx along the x axis and \a dy along - the y axis, and returns a reference to the matrix. - - \sa setMatrix() -*/ - -QMatrix &QMatrix::translate(qreal dx, qreal dy) -{ - _dx += dx*_m11 + dy*_m21; - _dy += dy*_m22 + dx*_m12; - return *this; -} - -/*! - \fn QMatrix &QMatrix::scale(qreal sx, qreal sy) - - Scales the coordinate system by \a sx horizontally and \a sy - vertically, and returns a reference to the matrix. - - \sa setMatrix() -*/ - -QMatrix &QMatrix::scale(qreal sx, qreal sy) -{ - _m11 *= sx; - _m12 *= sx; - _m21 *= sy; - _m22 *= sy; - return *this; -} - -/*! - Shears the coordinate system by \a sh horizontally and \a sv - vertically, and returns a reference to the matrix. - - \sa setMatrix() -*/ - -QMatrix &QMatrix::shear(qreal sh, qreal sv) -{ - qreal tm11 = sv*_m21; - qreal tm12 = sv*_m22; - qreal tm21 = sh*_m11; - qreal tm22 = sh*_m12; - _m11 += tm11; - _m12 += tm12; - _m21 += tm21; - _m22 += tm22; - return *this; -} - -const qreal deg2rad = qreal(0.017453292519943295769); // pi/180 - -/*! - \fn QMatrix &QMatrix::rotate(qreal degrees) - - Rotates the coordinate system the given \a degrees - counterclockwise. - - Note that if you apply a QMatrix to a point defined in widget - coordinates, the direction of the rotation will be clockwise - because the y-axis points downwards. - - Returns a reference to the matrix. - - \sa setMatrix() -*/ - -QMatrix &QMatrix::rotate(qreal a) -{ - qreal sina = 0; - qreal cosa = 0; - if (a == 90. || a == -270.) - sina = 1.; - else if (a == 270. || a == -90.) - sina = -1.; - else if (a == 180.) - cosa = -1.; - else{ - qreal b = deg2rad*a; // convert to radians - sina = qSin(b); // fast and convenient - cosa = qCos(b); - } - qreal tm11 = cosa*_m11 + sina*_m21; - qreal tm12 = cosa*_m12 + sina*_m22; - qreal tm21 = -sina*_m11 + cosa*_m21; - qreal tm22 = -sina*_m12 + cosa*_m22; - _m11 = tm11; _m12 = tm12; - _m21 = tm21; _m22 = tm22; - return *this; -} - -/*! - \fn bool QMatrix::isInvertible() const - - Returns \c true if the matrix is invertible, otherwise returns \c false. - - \sa inverted() -*/ - -/*! - \since 4.6 - \fn qreal QMatrix::determinant() const - - Returns the matrix's determinant. -*/ - -/*! - Returns an inverted copy of this matrix. - - If the matrix is singular (not invertible), the returned matrix is - the identity matrix. If \a invertible is valid (i.e. not 0), its - value is set to true if the matrix is invertible, otherwise it is - set to false. - - \sa isInvertible() -*/ - -QMatrix QMatrix::inverted(bool *invertible) const -{ - qreal dtr = determinant(); - if (dtr == 0.0) { - if (invertible) - *invertible = false; // singular matrix - return QMatrix(true); - } - else { // invertible matrix - if (invertible) - *invertible = true; - qreal dinv = 1.0/dtr; - return QMatrix((_m22*dinv), (-_m12*dinv), - (-_m21*dinv), (_m11*dinv), - ((_m21*_dy - _m22*_dx)*dinv), - ((_m12*_dx - _m11*_dy)*dinv), - true); - } -} - - -/*! - \fn bool QMatrix::operator==(const QMatrix &matrix) const - - Returns \c true if this matrix is equal to the given \a matrix, - otherwise returns \c false. -*/ - -bool QMatrix::operator==(const QMatrix &m) const -{ - return _m11 == m._m11 && - _m12 == m._m12 && - _m21 == m._m21 && - _m22 == m._m22 && - _dx == m._dx && - _dy == m._dy; -} - - -/*! - \since 5.6 - \relates QMatrix - - Returns the hash value for \a key, using - \a seed to seed the calculation. -*/ -uint qHash(const QMatrix &key, uint seed) noexcept -{ - QtPrivate::QHashCombine hash; - seed = hash(seed, key.m11()); - seed = hash(seed, key.m12()); - seed = hash(seed, key.m21()); - seed = hash(seed, key.m22()); - seed = hash(seed, key.dx()); - seed = hash(seed, key.dy()); - return seed; -} - -/*! - \fn bool QMatrix::operator!=(const QMatrix &matrix) const - - Returns \c true if this matrix is not equal to the given \a matrix, - otherwise returns \c false. -*/ - -bool QMatrix::operator!=(const QMatrix &m) const -{ - return _m11 != m._m11 || - _m12 != m._m12 || - _m21 != m._m21 || - _m22 != m._m22 || - _dx != m._dx || - _dy != m._dy; -} - -/*! - \fn QMatrix &QMatrix::operator *=(const QMatrix &matrix) - \overload - - Returns the result of multiplying this matrix by the given \a - matrix. -*/ - -QMatrix &QMatrix::operator *=(const QMatrix &m) -{ - qreal tm11 = _m11*m._m11 + _m12*m._m21; - qreal tm12 = _m11*m._m12 + _m12*m._m22; - qreal tm21 = _m21*m._m11 + _m22*m._m21; - qreal tm22 = _m21*m._m12 + _m22*m._m22; - - qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx; - qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy; - - _m11 = tm11; _m12 = tm12; - _m21 = tm21; _m22 = tm22; - _dx = tdx; _dy = tdy; - return *this; -} - -/*! - \fn QMatrix QMatrix::operator *(const QMatrix &matrix) const - - Returns the result of multiplying this matrix by the given \a - matrix. - - Note that matrix multiplication is not commutative, i.e. a*b != - b*a. -*/ - -QMatrix QMatrix::operator *(const QMatrix &m) const -{ - qreal tm11 = _m11*m._m11 + _m12*m._m21; - qreal tm12 = _m11*m._m12 + _m12*m._m22; - qreal tm21 = _m21*m._m11 + _m22*m._m21; - qreal tm22 = _m21*m._m12 + _m22*m._m22; - - qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx; - qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy; - return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true); -} - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -/*! - Assigns the given \a matrix's values to this matrix. -*/ -QMatrix &QMatrix::operator=(const QMatrix &matrix) noexcept -{ - _m11 = matrix._m11; - _m12 = matrix._m12; - _m21 = matrix._m21; - _m22 = matrix._m22; - _dx = matrix._dx; - _dy = matrix._dy; - return *this; -} -#endif - -/*! - \since 4.2 - - Returns the matrix as a QVariant. -*/ -QMatrix::operator QVariant() const -{ - return QVariant(QMetaType::QMatrix, this); -} - -Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m) -{ - return m.map(p); -} - - -/***************************************************************************** - QMatrix stream functions - *****************************************************************************/ -#ifndef QT_NO_DATASTREAM -/*! - \fn QDataStream &operator<<(QDataStream &stream, const QMatrix &matrix) - \relates QMatrix - - Writes the given \a matrix to the given \a stream and returns a - reference to the stream. - - \sa {Serializing Qt Data Types} -*/ - -QDataStream &operator<<(QDataStream &s, const QMatrix &m) -{ - if (s.version() == 1) { - s << (float)m.m11() << (float)m.m12() << (float)m.m21() - << (float)m.m22() << (float)m.dx() << (float)m.dy(); - } else { - s << double(m.m11()) - << double(m.m12()) - << double(m.m21()) - << double(m.m22()) - << double(m.dx()) - << double(m.dy()); - } - return s; -} - -/*! - \fn QDataStream &operator>>(QDataStream &stream, QMatrix &matrix) - \relates QMatrix - - Reads the given \a matrix from the given \a stream and returns a - reference to the stream. - - \sa {Serializing Qt Data Types} -*/ - -QDataStream &operator>>(QDataStream &s, QMatrix &m) -{ - if (s.version() == 1) { - float m11, m12, m21, m22, dx, dy; - s >> m11; s >> m12; s >> m21; s >> m22; - s >> dx; s >> dy; - m.setMatrix(m11, m12, m21, m22, dx, dy); - } - else { - double m11, m12, m21, m22, dx, dy; - s >> m11; - s >> m12; - s >> m21; - s >> m22; - s >> dx; - s >> dy; - m.setMatrix(m11, m12, m21, m22, dx, dy); - } - return s; -} -#endif // QT_NO_DATASTREAM - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug dbg, const QMatrix &m) -{ - QDebugStateSaver saver(dbg); - dbg.nospace() << "QMatrix(" - << "11=" << m.m11() - << " 12=" << m.m12() - << " 21=" << m.m21() - << " 22=" << m.m22() - << " dx=" << m.dx() - << " dy=" << m.dy() - << ')'; - return dbg; -} -#endif - -/*! - \fn bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2) - - \relates QMatrix - \since 4.6 - - \brief The qFuzzyCompare function is for comparing two matrices - using a fuzziness factor. - - Returns \c true if \a m1 and \a m2 are equal, allowing for a small - fuzziness factor for floating-point comparisons; false otherwise. -*/ - -QT_END_NAMESPACE diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h deleted file mode 100644 index a167260ade..0000000000 --- a/src/gui/painting/qmatrix.h +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtGui 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$ -** -****************************************************************************/ - -#ifndef QMATRIX_H -#define QMATRIX_H - -#include <QtGui/qtguiglobal.h> -#include <QtGui/qpolygon.h> -#include <QtGui/qregion.h> -#include <QtGui/qwindowdefs.h> -#include <QtCore/qline.h> -#include <QtCore/qpoint.h> -#include <QtCore/qrect.h> - -QT_BEGIN_NAMESPACE - - -class QPainterPath; -class QVariant; - -class Q_GUI_EXPORT QMatrix // 2D transform matrix -{ -public: - inline explicit QMatrix(Qt::Initialization) {} - QMatrix(); - QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy); - -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - // ### Qt 6: remove; the compiler-generated ones are fine! - QMatrix &operator=(QMatrix &&other) noexcept // = default - { memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QMatrix)); return *this; } - QMatrix &operator=(const QMatrix &) noexcept; // = default - QMatrix(QMatrix &&other) noexcept // = default - { memcpy(static_cast<void *>(this), static_cast<void *>(&other), sizeof(QMatrix)); } - QMatrix(const QMatrix &other) noexcept; // = default -#endif - - void setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, - qreal dx, qreal dy); - - qreal m11() const { return _m11; } - qreal m12() const { return _m12; } - qreal m21() const { return _m21; } - qreal m22() const { return _m22; } - qreal dx() const { return _dx; } - qreal dy() const { return _dy; } - - void map(int x, int y, int *tx, int *ty) const; - void map(qreal x, qreal y, qreal *tx, qreal *ty) const; - QRect mapRect(const QRect &) const; - QRectF mapRect(const QRectF &) const; - - QPoint map(const QPoint &p) const; - QPointF map(const QPointF&p) const; - QLine map(const QLine &l) const; - QLineF map(const QLineF &l) const; - QPolygonF map(const QPolygonF &a) const; - QPolygon map(const QPolygon &a) const; - QRegion map(const QRegion &r) const; - QPainterPath map(const QPainterPath &p) const; - QPolygon mapToPolygon(const QRect &r) const; - - void reset(); - inline bool isIdentity() const; - - QMatrix &translate(qreal dx, qreal dy); - QMatrix &scale(qreal sx, qreal sy); - QMatrix &shear(qreal sh, qreal sv); - QMatrix &rotate(qreal a); - - bool isInvertible() const { return !qFuzzyIsNull(_m11*_m22 - _m12*_m21); } - qreal determinant() const { return _m11*_m22 - _m12*_m21; } - - Q_REQUIRED_RESULT QMatrix inverted(bool *invertible = nullptr) const; - - bool operator==(const QMatrix &) const; - bool operator!=(const QMatrix &) const; - - QMatrix &operator*=(const QMatrix &); - QMatrix operator*(const QMatrix &o) const; - - operator QVariant() const; - -private: - inline QMatrix(bool) - : _m11(1.) - , _m12(0.) - , _m21(0.) - , _m22(1.) - , _dx(0.) - , _dy(0.) {} - inline QMatrix(qreal am11, qreal am12, qreal am21, qreal am22, qreal adx, qreal ady, bool) - : _m11(am11) - , _m12(am12) - , _m21(am21) - , _m22(am22) - , _dx(adx) - , _dy(ady) {} - friend class QTransform; - qreal _m11, _m12; - qreal _m21, _m22; - qreal _dx, _dy; -}; -Q_DECLARE_TYPEINFO(QMatrix, Q_MOVABLE_TYPE); - -Q_GUI_EXPORT Q_DECL_CONST_FUNCTION uint qHash(const QMatrix &key, uint seed = 0) noexcept; - -// mathematical semantics -inline QPoint operator*(const QPoint &p, const QMatrix &m) -{ return m.map(p); } -inline QPointF operator*(const QPointF &p, const QMatrix &m) -{ return m.map(p); } -inline QLineF operator*(const QLineF &l, const QMatrix &m) -{ return m.map(l); } -inline QLine operator*(const QLine &l, const QMatrix &m) -{ return m.map(l); } -inline QPolygon operator *(const QPolygon &a, const QMatrix &m) -{ return m.map(a); } -inline QPolygonF operator *(const QPolygonF &a, const QMatrix &m) -{ return m.map(a); } -inline QRegion operator *(const QRegion &r, const QMatrix &m) -{ return m.map(r); } -Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m); - -inline bool QMatrix::isIdentity() const -{ - return qFuzzyIsNull(_m11 - 1) && qFuzzyIsNull(_m22 - 1) && qFuzzyIsNull(_m12) - && qFuzzyIsNull(_m21) && qFuzzyIsNull(_dx) && qFuzzyIsNull(_dy); -} - -inline bool qFuzzyCompare(const QMatrix& m1, const QMatrix& m2) -{ - return qFuzzyCompare(m1.m11(), m2.m11()) - && qFuzzyCompare(m1.m12(), m2.m12()) - && qFuzzyCompare(m1.m21(), m2.m21()) - && qFuzzyCompare(m1.m22(), m2.m22()) - && qFuzzyCompare(m1.dx(), m2.dx()) - && qFuzzyCompare(m1.dy(), m2.dy()); -} - - -/***************************************************************************** - QMatrix stream functions - *****************************************************************************/ - -#ifndef QT_NO_DATASTREAM -Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix &); -Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix &); -#endif - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug, const QMatrix &); -#endif - -QT_END_NAMESPACE - -#endif // QMATRIX_H diff --git a/src/gui/painting/qpaintdevice.qdoc b/src/gui/painting/qpaintdevice.qdoc index 0cba864523..3b93faed84 100644 --- a/src/gui/painting/qpaintdevice.qdoc +++ b/src/gui/painting/qpaintdevice.qdoc @@ -39,8 +39,7 @@ right and Y increases downwards. The unit is one pixel. The drawing capabilities of QPaintDevice are currently implemented - by the QWidget, QImage, QPixmap, QGLPixelBuffer, QPicture, and - QPrinter subclasses. + by the QWidget, QImage, QPixmap, QPicture, and QPrinter subclasses. To implement support for a new backend, you must derive from QPaintDevice and reimplement the virtual paintEngine() function to diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 315bf0daf2..1785fcd12d 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -508,7 +508,7 @@ void QPaintEngine::drawEllipse(const QRectF &rect) if (hasFeature(PainterPaths)) { drawPath(path); } else { - QPolygonF polygon = path.toFillPolygon(QTransform()); + QPolygonF polygon = path.toFillPolygon(); drawPolygon(polygon.data(), polygon.size(), ConvexMode); } } diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index e90020dbbf..73727e463d 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -273,9 +273,6 @@ public: QBrush backgroundBrush() const; Qt::BGMode backgroundMode() const; QFont font() const; -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use transform()") QMatrix matrix() const; -#endif // QT_DEPRECATED_SINCE(5, 15) QTransform transform() const; Qt::ClipOperation clipOperation() const; diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 089aadc3f7..1244ea6709 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -434,14 +434,14 @@ public: QImage::Format prepare(QImage *image); - uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * qsizetype(bytes_per_line); } + uchar *scanLine(int y) { Q_ASSERT(y>=0); Q_ASSERT(y<m_height); return m_buffer + y * bytes_per_line; } int width() const { return m_width; } int height() const { return m_height; } - int bytesPerLine() const { return bytes_per_line; } + qsizetype bytesPerLine() const { return bytes_per_line; } int bytesPerPixel() const { return bytes_per_pixel; } template<typename T> - int stride() { return bytes_per_line / sizeof(T); } + int stride() { return static_cast<int>(bytes_per_line / sizeof(T)); } uchar *buffer() const { return m_buffer; } @@ -456,7 +456,7 @@ public: private: int m_width; int m_height; - int bytes_per_line; + qsizetype bytes_per_line; int bytes_per_pixel; uchar *m_buffer; }; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 390147463d..49f4d7be2e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -96,10 +96,15 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing -Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat); +static void qt_draw_decoration_for_glyphs(QPainter *painter, + const QPointF &decorationPosition, + const glyph_t *glyphArray, + const QFixedPoint *positions, + int glyphCount, + QFontEngine *fontEngine, + bool underline, + bool overline, + bool strikeOut); static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) { @@ -2555,19 +2560,19 @@ QRegion QPainter::clipRegion() const case QPainterClipInfo::PathClip: { QTransform matrix = (info.matrix * d->invMatrix); if (lastWasNothing) { - region = QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); lastWasNothing = false; continue; } if (info.operation == Qt::IntersectClip) { - region &= QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); } else if (info.operation == Qt::NoClip) { lastWasNothing = true; region = QRegion(); } else { - region = QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); } break; @@ -2891,175 +2896,6 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) d->updateState(d->state); } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \since 4.2 - \obsolete - - Sets the transformation matrix to \a matrix and enables transformations. - - \note It is advisable to use setWorldTransform() instead of this function to - preserve the properties of perspective transformations. - - If \a combine is true, then \a matrix is combined with the current - transformation matrix; otherwise \a matrix replaces the current - transformation matrix. - - If \a matrix is the identity matrix and \a combine is false, this - function calls setWorldMatrixEnabled(false). (The identity matrix is the - matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the - rest are 0.0.) - - The following functions can transform the coordinate system without using - a QMatrix: - \list - \li translate() - \li scale() - \li shear() - \li rotate() - \endlist - - They operate on the painter's worldMatrix() and are implemented like this: - - \snippet code/src_gui_painting_qpainter.cpp 4 - - Note that when using setWorldMatrix() function you should always have - \a combine be true when you are drawing into a QPicture. Otherwise - it may not be possible to replay the picture with additional - transformations; using the translate(), scale(), etc. convenience - functions is safe. - - For more information about the coordinate system, transformations - and window-viewport conversion, see \l {Coordinate System}. - - \sa setWorldTransform(), QTransform -*/ - -void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) -{ - setWorldTransform(QTransform(matrix), combine); -} - -/*! - \since 4.2 - \obsolete - - Returns the world transformation matrix. - - It is advisable to use worldTransform() because worldMatrix() does not - preserve the properties of perspective transformations. - - \sa {QPainter#Coordinate Transformations}{Coordinate Transformations}, - {Coordinate System} -*/ - -const QMatrix &QPainter::worldMatrix() const -{ - Q_D(const QPainter); - if (!d->engine) { - qWarning("QPainter::worldMatrix: Painter not active"); - return d->fakeState()->transform.toAffine(); - } - return d->state->worldMatrix.toAffine(); -} - -/*! - \obsolete - - Use setWorldTransform() instead. - - \sa setWorldTransform() -*/ - -void QPainter::setMatrix(const QMatrix &matrix, bool combine) -{ - setWorldTransform(QTransform(matrix), combine); -} - -/*! - \obsolete - - Use worldTransform() instead. - - \sa worldTransform() -*/ - -const QMatrix &QPainter::matrix() const -{ -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - return worldMatrix(); -QT_WARNING_POP -} - - -/*! - \since 4.2 - \obsolete - - Returns the transformation matrix combining the current - window/viewport and world transformation. - - It is advisable to use combinedTransform() instead of this - function to preserve the properties of perspective transformations. - - \sa setWorldTransform(), setWindow(), setViewport() -*/ -QMatrix QPainter::combinedMatrix() const -{ - return combinedTransform().toAffine(); -} - - -/*! - \obsolete - - Returns the matrix that transforms from logical coordinates to - device coordinates of the platform dependent paint device. - - \note It is advisable to use deviceTransform() instead of this - function to preserve the properties of perspective transformations. - - This function is \e only needed when using platform painting - commands on the platform dependent handle (Qt::HANDLE), and the - platform does not do transformations nativly. - - The QPaintEngine::PaintEngineFeature enum can be queried to - determine whether the platform performs the transformations or - not. - - \sa worldMatrix(), QPaintEngine::hasFeature(), -*/ -const QMatrix &QPainter::deviceMatrix() const -{ - Q_D(const QPainter); - if (!d->engine) { - qWarning("QPainter::deviceMatrix: Painter not active"); - return d->fakeState()->transform.toAffine(); - } - return d->state->matrix.toAffine(); -} - -/*! - \obsolete - - Resets any transformations that were made using translate(), scale(), - shear(), rotate(), setWorldMatrix(), setViewport() and - setWindow(). - - It is advisable to use resetTransform() instead of this function - to preserve the properties of perspective transformations. - - \sa {QPainter#Coordinate Transformations}{Coordinate - Transformations} -*/ - -void QPainter::resetMatrix() -{ - resetTransform(); -} -#endif - /*! \since 4.2 @@ -3109,34 +2945,6 @@ bool QPainter::worldMatrixEnabled() const return d->state->WxF; } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \obsolete - - Use setWorldMatrixEnabled() instead. - - \sa setWorldMatrixEnabled() -*/ - -void QPainter::setMatrixEnabled(bool enable) -{ - setWorldMatrixEnabled(enable); -} - -/*! - \obsolete - - Use worldMatrixEnabled() instead - - \sa worldMatrixEnabled() -*/ - -bool QPainter::matrixEnabled() const -{ - return worldMatrixEnabled(); -} -#endif - /*! Scales the coordinate system by (\a{sx}, \a{sy}). @@ -5607,40 +5415,31 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition); } - d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, fontD->fontEngine, - glyphRun.overline(), glyphRun.underline(), glyphRun.strikeOut()); + d->drawGlyphs(engineRequiresPretransformedGlyphPositions + ? d->state->transform().map(position) + : position, + glyphIndexes, + fixedPointPositions.data(), + count, + fontD->fontEngine, + glyphRun.overline(), + glyphRun.underline(), + glyphRun.strikeOut()); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions, +void QPainterPrivate::drawGlyphs(const QPointF &decorationPosition, + const quint32 *glyphArray, + QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, bool overline, bool underline, + QFontEngine *fontEngine, + bool overline, + bool underline, bool strikeOut) { Q_Q(QPainter); updateState(state); - QFixed leftMost; - QFixed rightMost; - QFixed baseLine; - for (int i=0; i<glyphCount; ++i) { - glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); - if (i == 0 || leftMost > positions[i].x) - leftMost = positions[i].x; - - // We don't support glyphs that do not share a common baseline. If this turns out to - // be a relevant use case, then we need to find clusters of glyphs that share a baseline - // and do a drawTextItemDecorations call per cluster. - if (i == 0 || baseLine < positions[i].y) - baseLine = positions[i].y; - - // We use the advance rather than the actual bounds to match the algorithm in drawText() - if (i == 0 || rightMost < positions[i].x + gm.xoff) - rightMost = positions[i].x + gm.xoff; - } - - QFixed width = rightMost - leftMost; - if (extended != nullptr && state->matrix.isAffine()) { QStaticTextItem staticTextItem; staticTextItem.color = state->pen.color(); @@ -5674,21 +5473,15 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio engine->drawTextItem(QPointF(0, 0), textItem); } - QTextItemInt::RenderFlags flags; - if (underline) - flags |= QTextItemInt::Underline; - if (overline) - flags |= QTextItemInt::Overline; - if (strikeOut) - flags |= QTextItemInt::StrikeOut; - - drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), - fontEngine, - nullptr, // textEngine - (underline - ? QTextCharFormat::SingleUnderline - : QTextCharFormat::NoUnderline), - flags, width.toReal(), QTextCharFormat()); + qt_draw_decoration_for_glyphs(q, + decorationPosition, + glyphArray, + positions, + glyphCount, + fontEngine, + underline, + overline, + strikeOut); } #endif // QT_NO_RAWFONT @@ -5868,9 +5661,15 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText } d->extended->drawStaticTextItem(item); - qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions, - item->numGlyphs, item->fontEngine(), staticText_d->font, - QTextCharFormat()); + qt_draw_decoration_for_glyphs(this, + topLeftPosition, + item->glyphs, + item->glyphPositions, + item->numGlyphs, + item->fontEngine(), + staticText_d->font.underline(), + staticText_d->font.overline(), + staticText_d->font.strikeOut()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6375,49 +6174,44 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setRenderHint(QPainter::Qt4CompatiblePainting); } -Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat) +static void qt_draw_decoration_for_glyphs(QPainter *painter, + const QPointF &decorationPosition, + const glyph_t *glyphArray, + const QFixedPoint *positions, + int glyphCount, + QFontEngine *fontEngine, + bool underline, + bool overline, + bool strikeOut) { - if (!(font.underline() || font.strikeOut() || font.overline())) + if (!underline && !overline && !strikeOut) return; - QFixed leftMost; - QFixed rightMost; - QFixed baseLine; - for (int i=0; i<glyphCount; ++i) { - glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); - if (i == 0 || leftMost > positions[i].x) - leftMost = positions[i].x; - - // We don't support glyphs that do not share a common baseline. If this turns out to - // be a relevant use case, then we need to find clusters of glyphs that share a baseline - // and do a drawTextItemDecoration call per cluster. - if (i == 0 || baseLine < positions[i].y) - baseLine = positions[i].y; - - // We use the advance rather than the actual bounds to match the algorithm in drawText() - if (i == 0 || rightMost < positions[i].x + gm.xoff) - rightMost = positions[i].x + gm.xoff; - } - - QFixed width = rightMost - leftMost; QTextItem::RenderFlags flags; - - if (font.underline()) + if (underline) flags |= QTextItem::Underline; - if (font.overline()) + if (overline) flags |= QTextItem::Overline; - if (font.strikeOut()) + if (strikeOut) flags |= QTextItem::StrikeOut; - drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), + bool rtl = positions[glyphCount - 1].x < positions[0].x; + QFixed baseline = positions[0].y; + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[rtl ? 0 : glyphCount - 1]); + + qreal width = rtl + ? (positions[0].x + gm.xoff - positions[glyphCount - 1].x).toReal() + : (positions[glyphCount - 1].x + gm.xoff - positions[0].x).toReal(); + + drawTextItemDecoration(painter, + QPointF(decorationPosition.x(), baseline.toReal()), fontEngine, nullptr, // textEngine - font.underline() ? QTextCharFormat::SingleUnderline - : QTextCharFormat::NoUnderline, flags, - width.toReal(), charFormat); + underline ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline, + flags, + width, + QTextCharFormat()); } void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) @@ -8084,33 +7878,6 @@ QFont QPaintEngineState::font() const return static_cast<const QPainterState *>(this)->font; } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \since 4.2 - \obsolete - - Use transform() instead. - - Returns the matrix in the current paint engine - state. - - \note It is advisable to use transform() instead of this function to - preserve the properties of perspective transformations. - - This variable should only be used when the state() returns a - combination which includes the QPaintEngine::DirtyTransform flag. - - \sa state(), QPaintEngine::updateState() -*/ - -QMatrix QPaintEngineState::matrix() const -{ - const QPainterState *st = static_cast<const QPainterState *>(this); - - return st->matrix.toAffine(); -} -#endif - /*! \since 4.3 diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 77c6504d2e..52de8b6839 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -53,7 +53,6 @@ #include <QtGui/qpolygon.h> #include <QtGui/qpen.h> #include <QtGui/qbrush.h> -#include <QtGui/qmatrix.h> #include <QtGui/qtransform.h> #include <QtGui/qfontinfo.h> #include <QtGui/qfontmetrics.h> @@ -236,35 +235,11 @@ public: void restore(); // XForm functions -#if QT_DEPRECATED_SINCE(5, 13) - QT_DEPRECATED_X("Use setTransform() instead") - void setMatrix(const QMatrix &matrix, bool combine = false); - QT_DEPRECATED_X("Use transform() instead") - const QMatrix &matrix() const; - QT_DEPRECATED_X("Use deviceTransform() instead") - const QMatrix &deviceMatrix() const; - QT_DEPRECATED_X("Use resetTransform() instead") - void resetMatrix(); -#endif - void setTransform(const QTransform &transform, bool combine = false); const QTransform &transform() const; const QTransform &deviceTransform() const; void resetTransform(); -#if QT_DEPRECATED_SINCE(5, 13) - QT_DEPRECATED_X("Use setWorldTransform() instead") - void setWorldMatrix(const QMatrix &matrix, bool combine = false); - QT_DEPRECATED_X("Use worldTransform() instead") - const QMatrix &worldMatrix() const; - QT_DEPRECATED_X("Use combinedTransform() instead") - QMatrix combinedMatrix() const; - QT_DEPRECATED_X("Use setWorldMatrixEnabled() instead") - void setMatrixEnabled(bool enabled); - QT_DEPRECATED_X("Use worldMatrixEnabled() instead") - bool matrixEnabled() const; -#endif - void setWorldTransform(const QTransform &matrix, bool combine = false); const QTransform &worldTransform() const; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index dafd6e33be..870381d48a 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -235,7 +235,7 @@ public: void drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine); #if !defined(QT_NO_RAWFONT) - void drawGlyphs(const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount, + void drawGlyphs(const QPointF &decorationPosition, const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount, QFontEngine *fontEngine, bool overline = false, bool underline = false, bool strikeOut = false); #endif diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index ab60afd9cd..11623c78f0 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -44,7 +44,6 @@ #include <qdebug.h> #include <qiodevice.h> #include <qlist.h> -#include <qmatrix.h> #include <qpen.h> #include <qpolygon.h> #include <qtextlayout.h> @@ -1604,6 +1603,25 @@ QPainterPath QPainterPath::toReversed() const } /*! + \overload + + Converts the path into a list of polygons without any transformation, + and returns the list. + + This function creates one polygon for each subpath regardless of + intersecting subpaths (i.e. overlapping bounding rectangles). To + make sure that such overlapping subpaths are filled correctly, use + the toFillPolygons() function instead. + + \sa toFillPolygons(), toFillPolygon(), {QPainterPath#QPainterPath + Conversion}{QPainterPath Conversion} +*/ +QList<QPolygonF> QPainterPath::toSubpathPolygons() const +{ + return toSubpathPolygons(QTransform()); +} + +/*! Converts the path into a list of polygons using the QTransform \a matrix, and returns the list. @@ -1660,18 +1678,34 @@ QList<QPolygonF> QPainterPath::toSubpathPolygons(const QTransform &matrix) const return flatCurves; } -#if QT_DEPRECATED_SINCE(5, 15) /*! - \overload - \obsolete + \overload - Use toSubpathPolygons(const QTransform &matrix) instead. - */ -QList<QPolygonF> QPainterPath::toSubpathPolygons(const QMatrix &matrix) const + Converts the path into a list of polygons without any transformation, + and returns the list. + + The function differs from the toFillPolygon() function in that it + creates several polygons. It is provided because it is usually + faster to draw several small polygons than to draw one large + polygon, even though the total number of points drawn is the same. + + The toFillPolygons() function differs from the toSubpathPolygons() + function in that it create only polygon for subpaths that have + overlapping bounding rectangles. + + Like the toFillPolygon() function, this function uses a rewinding + technique to make sure that overlapping subpaths can be filled + using the correct fill rule. Note that rewinding inserts addition + lines in the polygons so the outline of the fill polygon does not + match the outline of the path. + + \sa toSubpathPolygons(), toFillPolygon(), + {QPainterPath#QPainterPath Conversion}{QPainterPath Conversion} +*/ +QList<QPolygonF> QPainterPath::toFillPolygons() const { - return toSubpathPolygons(QTransform(matrix)); + return toFillPolygons(QTransform()); } -#endif // QT_DEPRECATED_SINCE(5, 15) /*! Converts the path into a list of polygons using the @@ -1792,19 +1826,6 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const return polys; } -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \overload - \obsolete - - Use toFillPolygons(const QTransform &matrix) instead. - */ -QList<QPolygonF> QPainterPath::toFillPolygons(const QMatrix &matrix) const -{ - return toFillPolygons(QTransform(matrix)); -} -#endif // QT_DEPRECATED_SINCE(5, 15) - //same as qt_polygon_isect_line in qpolygon.cpp static void qt_painterpath_isect_line(const QPointF &p1, const QPointF &p2, @@ -2882,6 +2903,28 @@ void QPainterPathStroker::setDashOffset(qreal offset) } /*! + \overload + + Converts the path into a polygon without any transformation, + and returns the polygon. + + The polygon is created by first converting all subpaths to + polygons, then using a rewinding technique to make sure that + overlapping subpaths can be filled using the correct fill rule. + + Note that rewinding inserts addition lines in the polygon so + the outline of the fill polygon does not match the outline of + the path. + + \sa toSubpathPolygons(), toFillPolygons(), + {QPainterPath#QPainterPath Conversion}{QPainterPath Conversion} +*/ +QPolygonF QPainterPath::toFillPolygon() const +{ + return toFillPolygon(QTransform()); +} + +/*! Converts the path into a polygon using the QTransform \a matrix, and returns the polygon. @@ -2898,7 +2941,6 @@ void QPainterPathStroker::setDashOffset(qreal offset) */ QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const { - const QList<QPolygonF> flats = toSubpathPolygons(matrix); QPolygonF polygon; if (flats.isEmpty()) @@ -2914,19 +2956,6 @@ QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const return polygon; } -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \overload - \obsolete - - Use toFillPolygon(const QTransform &matrix) instead. -*/ -QPolygonF QPainterPath::toFillPolygon(const QMatrix &matrix) const -{ - return toFillPolygon(QTransform(matrix)); -} -#endif // QT_DEPRECATED_SINCE(5, 15) - //derivative of the equation static inline qreal slopeAt(qreal t, qreal a, qreal b, qreal c, qreal d) { diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 26b92dc6fa..078b665222 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -41,7 +41,6 @@ #define QPAINTERPATH_H #include <QtGui/qtguiglobal.h> -#include <QtGui/qmatrix.h> #include <QtCore/qglobal.h> #include <QtCore/qrect.h> #include <QtCore/qline.h> @@ -59,6 +58,7 @@ class QPainterPathStrokerPrivate; class QPen; class QPolygonF; class QRegion; +class QTransform; class QVectorPath; class Q_GUI_EXPORT QPainterPath @@ -176,16 +176,11 @@ public: Q_REQUIRED_RESULT QPainterPath toReversed() const; -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use toSubpathPolygons(const QTransform &)") - QList<QPolygonF> toSubpathPolygons(const QMatrix &matrix = QMatrix()) const; - QT_DEPRECATED_X("Use toFillPolygons(const QTransform &") - QList<QPolygonF> toFillPolygons(const QMatrix &matrix = QMatrix()) const; - QT_DEPRECATED_X("Use toFillPolygon(const QTransform &)") - QPolygonF toFillPolygon(const QMatrix &matrix = QMatrix()) const; -#endif // QT_DEPRECATED_SINCE(5, 15) + QList<QPolygonF> toSubpathPolygons() const; QList<QPolygonF> toSubpathPolygons(const QTransform &matrix) const; + QList<QPolygonF> toFillPolygons() const; QList<QPolygonF> toFillPolygons(const QTransform &matrix) const; + QPolygonF toFillPolygon() const; QPolygonF toFillPolygon(const QTransform &matrix) const; int elementCount() const; @@ -238,7 +233,6 @@ private: friend class QPainterPathData; friend class QPainterPathStroker; friend class QPainterPathStrokerPrivate; - friend class QMatrix; friend class QTransform; friend class QVectorPath; friend Q_GUI_EXPORT const QVectorPath &qtVectorPathForPath(const QPainterPath &); diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h index a420e0b3d9..d52243b0df 100644 --- a/src/gui/painting/qpainterpath_p.h +++ b/src/gui/painting/qpainterpath_p.h @@ -74,7 +74,6 @@ public: friend class QPainterPathData; friend class QPainterPathStroker; friend class QPainterPathStrokerPrivate; - friend class QMatrix; friend class QTransform; friend class QVectorPath; friend struct QPainterPathPrivateDeleter; diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index c092a7153f..e8ac494e04 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -40,43 +40,8 @@ #include "qplatformbackingstore.h" #include <qwindow.h> #include <qpixmap.h> -#include <private/qwindow_p.h> - -#include <qopengl.h> -#include <qopenglcontext.h> -#include <QtGui/QMatrix4x4> -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> -#ifndef QT_NO_OPENGL -#include <QtGui/qopengltextureblitter.h> -#include <QtGui/qoffscreensurface.h> -#endif -#include <qpa/qplatformgraphicsbuffer.h> -#include <qpa/qplatformgraphicsbufferhelper.h> -#ifndef GL_TEXTURE_BASE_LEVEL -#define GL_TEXTURE_BASE_LEVEL 0x813C -#endif -#ifndef GL_TEXTURE_MAX_LEVEL -#define GL_TEXTURE_MAX_LEVEL 0x813D -#endif -#ifndef GL_UNPACK_ROW_LENGTH -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#endif -#ifndef GL_RGB10_A2 -#define GL_RGB10_A2 0x8059 -#endif -#ifndef GL_UNSIGNED_INT_2_10_10_10_REV -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#endif - -#ifndef GL_FRAMEBUFFER_SRGB -#define GL_FRAMEBUFFER_SRGB 0x8DB9 -#endif -#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE -#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA -#endif +#include <QtCore/private/qobject_p.h> QT_BEGIN_NAMESPACE @@ -88,38 +53,19 @@ public: QPlatformBackingStorePrivate(QWindow *w) : window(w) , backingStore(nullptr) -#ifndef QT_NO_OPENGL - , textureId(0) - , blitter(nullptr) -#endif { } ~QPlatformBackingStorePrivate() { #ifndef QT_NO_OPENGL - if (context) { - QOffscreenSurface offscreenSurface; - offscreenSurface.setFormat(context->format()); - offscreenSurface.create(); - context->makeCurrent(&offscreenSurface); - if (textureId) - context->functions()->glDeleteTextures(1, &textureId); - if (blitter) - blitter->destroy(); - } - delete blitter; + delete openGLSupport; #endif } QWindow *window; QBackingStore *backingStore; #ifndef QT_NO_OPENGL - QScopedPointer<QOpenGLContext> context; - mutable GLuint textureId; - mutable QSize textureSize; - mutable bool needsSwizzle; - mutable bool premultiplied; - QOpenGLTextureBlitter *blitter; + QPlatformBackingStoreOpenGLSupportBase *openGLSupport = nullptr; #endif }; @@ -240,83 +186,20 @@ void QPlatformTextureList::clear() */ #ifndef QT_NO_OPENGL - -static inline QRect deviceRect(const QRect &rect, QWindow *window) -{ - QRect deviceRect(rect.topLeft() * window->devicePixelRatio(), - rect.size() * window->devicePixelRatio()); - return deviceRect; -} - -static inline QPoint deviceOffset(const QPoint &pt, QWindow *window) -{ - return pt * window->devicePixelRatio(); -} - -static QRegion deviceRegion(const QRegion ®ion, QWindow *window, const QPoint &offset) -{ - if (offset.isNull() && window->devicePixelRatio() <= 1) - return region; - - QVector<QRect> rects; - rects.reserve(region.rectCount()); - for (const QRect &rect : region) - rects.append(deviceRect(rect.translated(offset), window)); - - QRegion deviceRegion; - deviceRegion.setRects(rects.constData(), rects.count()); - return deviceRegion; -} - -static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) -{ - return QRect(topLeftRect.x(), windowHeight - topLeftRect.bottomRight().y() - 1, - topLeftRect.width(), topLeftRect.height()); -} - -static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, - QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb) -{ - const QRect clipRect = textures->clipRect(idx); - if (clipRect.isEmpty()) - return; - - QRect rectInWindow = textures->geometry(idx); - // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust - rectInWindow.translate(-offset); - - const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft()); - const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height()); - - const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(deviceRect(clippedRectInWindow, window), - deviceWindowRect); - - const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window), - deviceRect(rectInWindow, window).size(), - QOpenGLTextureBlitter::OriginBottomLeft); - - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); - const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb); - if (srgb && canUseSrgb) - funcs->glEnable(GL_FRAMEBUFFER_SRGB); - - blitter->blit(textures->textureId(idx), target, source); - - if (srgb && canUseSrgb) - funcs->glDisable(GL_FRAMEBUFFER_SRGB); -} - /*! Flushes the given \a region from the specified \a window onto the screen, and composes it with the specified \a textures. - The default implementation retrieves the contents using toTexture() + If OpenGLSupport has been enabled using \c setOpenGLSupport, + the default implementation retrieves the contents using toTexture() and composes using OpenGL. May be reimplemented in subclasses if there is a more efficient native way to do it. \note \a region is relative to the window which may not be top-level in case \a window corresponds to a native child widget. \a offset is the position of the native child relative to the top-level window. + + \sa setOpenGLSupport() */ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, @@ -324,162 +207,13 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i QPlatformTextureList *textures, bool translucentBackground) { - if (!qt_window_private(window)->receivedExpose) - return; - - if (!d_ptr->context) { - d_ptr->context.reset(new QOpenGLContext); - d_ptr->context->setFormat(d_ptr->window->requestedFormat()); - d_ptr->context->setScreen(d_ptr->window->screen()); - d_ptr->context->setShareContext(qt_window_private(d_ptr->window)->shareContext()); - if (!d_ptr->context->create()) { - qCWarning(lcQpaBackingStore, "composeAndFlush: QOpenGLContext creation failed"); - return; - } - } - - bool current = d_ptr->context->makeCurrent(window); - - if (!current && !d_ptr->context->isValid()) { - delete d_ptr->blitter; - d_ptr->blitter = nullptr; - d_ptr->textureId = 0; - current = d_ptr->context->create() && d_ptr->context->makeCurrent(window); - } - - if (!current) { - qCWarning(lcQpaBackingStore, "composeAndFlush: makeCurrent() failed"); - return; - } - - qCDebug(lcQpaBackingStore) << "Composing and flushing" << region << "of" << window - << "at offset" << offset << "with" << textures->count() << "texture(s) in" << textures; - - QWindowPrivate::get(window)->lastComposeTime.start(); - - QOpenGLFunctions *funcs = d_ptr->context->functions(); - funcs->glViewport(0, 0, qRound(window->width() * window->devicePixelRatio()), qRound(window->height() * window->devicePixelRatio())); - funcs->glClearColor(0, 0, 0, translucentBackground ? 0 : 1); - funcs->glClear(GL_COLOR_BUFFER_BIT); - - if (!d_ptr->blitter) { - d_ptr->blitter = new QOpenGLTextureBlitter; - d_ptr->blitter->create(); - } - - d_ptr->blitter->bind(); - - const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window); - const QPoint deviceWindowOffset = deviceOffset(offset, window); - - bool canUseSrgb = false; - // If there are any sRGB textures in the list, check if the destination - // framebuffer is sRGB capable. - for (int i = 0; i < textures->count(); ++i) { - if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) { - GLint cap = 0; - funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap); - if (cap) - canUseSrgb = true; - break; - } - } - - // Textures for renderToTexture widgets. - for (int i = 0; i < textures->count(); ++i) { - if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); - } - - // Backingstore texture with the normal widgets. - GLuint textureId = 0; - QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft; - if (QPlatformGraphicsBuffer *graphicsBuffer = this->graphicsBuffer()) { - if (graphicsBuffer->size() != d_ptr->textureSize) { - if (d_ptr->textureId) - funcs->glDeleteTextures(1, &d_ptr->textureId); - funcs->glGenTextures(1, &d_ptr->textureId); - funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - } - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied)) { - d_ptr->textureSize = graphicsBuffer->size(); - } else { - d_ptr->textureSize = QSize(0,0); - } - - graphicsBuffer->unlock(); - } else if (!region.isEmpty()){ - funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied); - graphicsBuffer->unlock(); - } - - if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) - origin = QOpenGLTextureBlitter::OriginBottomLeft; - textureId = d_ptr->textureId; - } else { - TextureFlags flags; - textureId = toTexture(deviceRegion(region, window, offset), &d_ptr->textureSize, &flags); - d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0; - d_ptr->premultiplied = (flags & TexturePremultiplied) != 0; - if (flags & TextureFlip) - origin = QOpenGLTextureBlitter::OriginBottomLeft; - } - - funcs->glEnable(GL_BLEND); - if (d_ptr->premultiplied) - funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + if (auto *c = d_ptr->openGLSupport) + c->composeAndFlush(window, region, offset, textures, translucentBackground); else - funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - - if (textureId) { - if (d_ptr->needsSwizzle) - d_ptr->blitter->setRedBlueSwizzle(true); - // The backingstore is for the entire tlw. - // In case of native children offset tells the position relative to the tlw. - const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(deviceWindowOffset), d_ptr->textureSize.height()); - const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(srcRect, - d_ptr->textureSize, - origin); - d_ptr->blitter->blit(textureId, QMatrix4x4(), source); - if (d_ptr->needsSwizzle) - d_ptr->blitter->setRedBlueSwizzle(false); - } - - // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. - bool blendIsPremultiplied = d_ptr->premultiplied; - for (int i = 0; i < textures->count(); ++i) { - const QPlatformTextureList::Flags flags = textures->flags(i); - if (flags.testFlag(QPlatformTextureList::NeedsPremultipliedAlphaBlending)) { - if (!blendIsPremultiplied) { - funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - blendIsPremultiplied = true; - } - } else { - if (blendIsPremultiplied) { - funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - blendIsPremultiplied = false; - } - } - if (flags.testFlag(QPlatformTextureList::StacksOnTop)) - blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb); - } - - funcs->glDisable(GL_BLEND); - d_ptr->blitter->release(); - - d_ptr->context->swapBuffers(window); + qWarning() << Q_FUNC_INFO << "no opengl support set"; } #endif + /*! Implemented in subclasses to return the content of the backingstore as a QImage. @@ -504,7 +238,8 @@ QImage QPlatformBackingStore::toImage() const The ownership of the texture is not transferred. The caller must not store the return value between calls, but instead call this function before each use. - The default implementation returns a cached texture if \a dirtyRegion is empty and + If OpenGLSupport has been enabled using \c setOpenGLSupport, + the default implementation returns a cached texture if \a dirtyRegion is empty and \a textureSize matches the backingstore size, otherwise it retrieves the content using toImage() and performs a texture upload. This works only if the value of \a textureSize is preserved between the calls to this function. @@ -520,141 +255,17 @@ QImage QPlatformBackingStore::toImage() const flags will be set to include \c TextureFlip. \note \a dirtyRegion is relative to the backingstore so no adjustment is needed. + + \sa setOpenGLSupport() */ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const { - Q_ASSERT(textureSize); - Q_ASSERT(flags); - - QImage image = toImage(); - QSize imageSize = image.size(); - - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - GLenum internalFormat = GL_RGBA; - GLuint pixelType = GL_UNSIGNED_BYTE; - - bool needsConversion = false; - *flags = { }; - switch (image.format()) { - case QImage::Format_ARGB32_Premultiplied: - *flags |= TexturePremultiplied; - Q_FALLTHROUGH(); - case QImage::Format_RGB32: - case QImage::Format_ARGB32: - *flags |= TextureSwizzle; - break; - case QImage::Format_RGBA8888_Premultiplied: - *flags |= TexturePremultiplied; - Q_FALLTHROUGH(); - case QImage::Format_RGBX8888: - case QImage::Format_RGBA8888: - break; - case QImage::Format_BGR30: - case QImage::Format_A2BGR30_Premultiplied: - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; - internalFormat = GL_RGB10_A2; - *flags |= TexturePremultiplied; - } else { - needsConversion = true; - } - break; - case QImage::Format_RGB30: - case QImage::Format_A2RGB30_Premultiplied: - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; - internalFormat = GL_RGB10_A2; - *flags |= TextureSwizzle | TexturePremultiplied; - } else { - needsConversion = true; - } - break; - default: - needsConversion = true; - break; - } - if (imageSize.isEmpty()) { - *textureSize = imageSize; + if (auto *c = d_ptr->openGLSupport) + return c->toTexture(dirtyRegion, textureSize, flags); + else { + qWarning() << Q_FUNC_INFO << "no opengl support set"; return 0; } - - // Must rely on the input only, not d_ptr. - // With the default composeAndFlush() textureSize is &d_ptr->textureSize. - bool resized = *textureSize != imageSize; - if (dirtyRegion.isEmpty() && !resized) - return d_ptr->textureId; - - *textureSize = imageSize; - - if (needsConversion) - image = image.convertToFormat(QImage::Format_RGBA8888); - - // The image provided by the backingstore may have a stride larger than width * 4, for - // instance on platforms that manually implement client-side decorations. - static const int bytesPerPixel = 4; - const int strideInPixels = image.bytesPerLine() / bytesPerPixel; - const bool hasUnpackRowLength = !ctx->isOpenGLES() || ctx->format().majorVersion() >= 3; - - QOpenGLFunctions *funcs = ctx->functions(); - - if (hasUnpackRowLength) { - funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, strideInPixels); - } else if (strideInPixels != image.width()) { - // No UNPACK_ROW_LENGTH on ES 2.0 and yet we would need it. This case is typically - // hit with QtWayland which is rarely used in combination with a ES2.0-only GL - // implementation. Therefore, accept the performance hit and do a copy. - image = image.copy(); - } - - if (resized) { - if (d_ptr->textureId) - funcs->glDeleteTextures(1, &d_ptr->textureId); - funcs->glGenTextures(1, &d_ptr->textureId); - funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); - funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - } - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, imageSize.width(), imageSize.height(), 0, GL_RGBA, pixelType, - const_cast<uchar*>(image.constBits())); - } else { - funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QRect imageRect = image.rect(); - QRect rect = dirtyRegion.boundingRect() & imageRect; - - if (hasUnpackRowLength) { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, - image.constScanLine(rect.y()) + rect.x() * bytesPerPixel); - } else { - // if the rect is wide enough it's cheaper to just - // extend it instead of doing an image copy - if (rect.width() >= imageRect.width() / 2) { - rect.setX(0); - rect.setWidth(imageRect.width()); - } - - // if the sub-rect is full-width we can pass the image data directly to - // OpenGL instead of copying, since there's no gap between scanlines - - if (rect.width() == imageRect.width()) { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, - image.constScanLine(rect.y())); - } else { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, - image.copy(rect).constBits()); - } - } - } - - if (hasUnpackRowLength) - funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - - return d_ptr->textureId; } #endif // QT_NO_OPENGL @@ -706,6 +317,18 @@ QBackingStore *QPlatformBackingStore::backingStore() const return d_ptr->backingStore; } +#ifndef QT_NO_OPENGL +/*! + Injects an OpenGL implementation helper. Platform integrations need to + call this if they intend to use the default OpenGL implementations of + composeAndFlush or toTexture. +*/ +void QPlatformBackingStore::setOpenGLSupport(QPlatformBackingStoreOpenGLSupportBase *openGLSupport) +{ + d_ptr->openGLSupport = openGLSupport; +} +#endif // QT_NO_OPENGL + /*! This function is called before painting onto the surface begins, with the \a region in which the painting will occur. diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index 7aa054f1e2..2a3d7d20b5 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -67,11 +67,10 @@ class QRect; class QPoint; class QImage; class QPlatformBackingStorePrivate; -class QPlatformWindow; class QPlatformTextureList; class QPlatformTextureListPrivate; -class QOpenGLContext; class QPlatformGraphicsBuffer; +class QPlatformBackingStoreOpenGLSupportBase; #ifndef QT_NO_OPENGL class Q_GUI_EXPORT QPlatformTextureList : public QObject @@ -118,6 +117,8 @@ public: QWindow *window() const; QBackingStore *backingStore() const; + void setOpenGLSupport(QPlatformBackingStoreOpenGLSupportBase *openGLSupport); + virtual QPaintDevice *paintDevice() = 0; virtual void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) = 0; @@ -154,6 +155,17 @@ private: }; #ifndef QT_NO_OPENGL +class Q_GUI_EXPORT QPlatformBackingStoreOpenGLSupportBase // pure interface +{ +public: + virtual void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, + QPlatformTextureList *textures, bool translucentBackground) = 0; + virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, QPlatformBackingStore::TextureFlags *flags) const = 0; + virtual ~QPlatformBackingStoreOpenGLSupportBase() {} +}; +#endif // QT_NO_OPENGL + +#ifndef QT_NO_OPENGL Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformBackingStore::TextureFlags) #endif diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp index 4fe819cae0..e9a8793bd0 100644 --- a/src/gui/painting/qpolygon.cpp +++ b/src/gui/painting/qpolygon.cpp @@ -899,7 +899,7 @@ QPolygon QPolygon::united(const QPolygon &r) const QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.united(clip).toFillPolygon(QTransform()).toPolygon(); + return subject.united(clip).toFillPolygon().toPolygon(); } /*! @@ -918,7 +918,7 @@ QPolygon QPolygon::intersected(const QPolygon &r) const QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.intersected(clip).toFillPolygon(QTransform()).toPolygon(); + return subject.intersected(clip).toFillPolygon().toPolygon(); } /*! @@ -936,7 +936,7 @@ QPolygon QPolygon::subtracted(const QPolygon &r) const QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.subtracted(clip).toFillPolygon(QTransform()).toPolygon(); + return subject.subtracted(clip).toFillPolygon().toPolygon(); } /*! @@ -975,7 +975,7 @@ QPolygonF QPolygonF::united(const QPolygonF &r) const QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.united(clip).toFillPolygon(QTransform()); + return subject.united(clip).toFillPolygon(); } /*! @@ -994,7 +994,7 @@ QPolygonF QPolygonF::intersected(const QPolygonF &r) const QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.intersected(clip).toFillPolygon(QTransform()); + return subject.intersected(clip).toFillPolygon(); } /*! @@ -1011,7 +1011,7 @@ QPolygonF QPolygonF::subtracted(const QPolygonF &r) const { QPainterPath subject; subject.addPolygon(*this); QPainterPath clip; clip.addPolygon(r); - return subject.subtracted(clip).toFillPolygon(QTransform()); + return subject.subtracted(clip).toFillPolygon(); } /*! diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h index 93fab55aa1..584965af3b 100644 --- a/src/gui/painting/qpolygon.h +++ b/src/gui/painting/qpolygon.h @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE - -class QMatrix; class QTransform; class QRect; class QVariant; diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index bac042c784..6409ab9528 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -3917,7 +3917,7 @@ QRegion::QRegion(const QRect &r, RegionType t) } else if (t == Ellipse) { QPainterPath path; path.addEllipse(r.x(), r.y(), r.width(), r.height()); - QPolygon a = path.toSubpathPolygons(QTransform()).at(0).toPolygon(); + QPolygon a = path.toSubpathPolygons().at(0).toPolygon(); d->qt_rgn = PolygonRegion(a.constData(), a.size(), EvenOddRule); } } diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 91214f27ca..e906397520 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -350,7 +350,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP int mw = qMin(mask.width(), c.w); int mh = qMin(mask.height(), c.h); uchar *d = m_image.bits(); - int dbpl = m_image.bytesPerLine(); + qsizetype dbpl = m_image.bytesPerLine(); for (int y = 0; y < c.h; ++y) { uchar *dest = d + (c.y + y) *dbpl + c.x/8; @@ -372,7 +372,7 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g, QFixed subP int mw = qMin(mask.width(), c.w); int mh = qMin(mask.height(), c.h); uchar *d = m_image.bits(); - int dbpl = m_image.bytesPerLine(); + qsizetype dbpl = m_image.bytesPerLine(); if (mask.depth() == 1) { for (int y = 0; y < c.h; ++y) { diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 9d8bb0c3e2..4adc2b075e 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -41,7 +41,6 @@ #include "qdatastream.h" #include "qdebug.h" #include "qhashfunctions.h" -#include "qmatrix.h" #include "qregion.h" #include "qpainterpath.h" #include "qpainterpath_p.h" @@ -76,20 +75,20 @@ static void nanWarning(const char *func) ny = FY_; \ break; \ case TxTranslate: \ - nx = FX_ + affine._dx; \ - ny = FY_ + affine._dy; \ + nx = FX_ + m_matrix[2][0]; \ + ny = FY_ + m_matrix[2][1]; \ break; \ case TxScale: \ - nx = affine._m11 * FX_ + affine._dx; \ - ny = affine._m22 * FY_ + affine._dy; \ + nx = m_matrix[0][0] * FX_ + m_matrix[2][0]; \ + ny = m_matrix[1][1] * FY_ + m_matrix[2][1]; \ break; \ case TxRotate: \ case TxShear: \ case TxProject: \ - nx = affine._m11 * FX_ + affine._m21 * FY_ + affine._dx; \ - ny = affine._m12 * FX_ + affine._m22 * FY_ + affine._dy; \ + nx = m_matrix[0][0] * FX_ + m_matrix[1][0] * FY_ + m_matrix[2][0]; \ + ny = m_matrix[0][1] * FX_ + m_matrix[1][1] * FY_ + m_matrix[2][1]; \ if (t == TxProject) { \ - qreal w = (m_13 * FX_ + m_23 * FY_ + m_33); \ + qreal w = (m_matrix[0][2] * FX_ + m_matrix[1][2] * FY_ + m_matrix[2][2]); \ if (w < qreal(Q_NEAR_CLIP)) w = qreal(Q_NEAR_CLIP); \ w = 1./w; \ nx *= w; \ @@ -109,14 +108,6 @@ static void nanWarning(const char *func) or project the coordinate system, and is typically used when rendering graphics. - QTransform differs from QMatrix in that it is a true 3x3 matrix, - allowing perspective transformations. QTransform's toAffine() - method allows casting QTransform to QMatrix. If a perspective - transformation has been specified on the matrix, then the - conversion will cause loss of data. - - QTransform is the recommended transformation class in Qt. - A QTransform object can be built using the setMatrix(), scale(), rotate(), translate() and shear() functions. Alternatively, it can be built by applying \l {QTransform#Basic Matrix @@ -261,8 +252,7 @@ static void nanWarning(const char *func) \sa reset() */ QTransform::QTransform() - : affine(true) - , m_13(0), m_23(0), m_33(1) + : m_matrix{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1} } , m_type(TxNone) , m_dirty(TxNone) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -282,8 +272,7 @@ QTransform::QTransform() QTransform::QTransform(qreal h11, qreal h12, qreal h13, qreal h21, qreal h22, qreal h23, qreal h31, qreal h32, qreal h33) - : affine(h11, h12, h21, h22, h31, h32, true) - , m_13(h13), m_23(h23), m_33(h33) + : m_matrix{ {h11, h12, h13}, {h21, h22, h23}, {h31, h32, h33} } , m_type(TxNone) , m_dirty(TxProject) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -301,8 +290,7 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13, */ QTransform::QTransform(qreal h11, qreal h12, qreal h21, qreal h22, qreal dx, qreal dy) - : affine(h11, h12, h21, h22, dx, dy, true) - , m_13(0), m_23(0), m_33(1) + : m_matrix{ {h11, h12, 0}, {h21, h22, 0}, {dx, dy, 1} } , m_type(TxNone) , m_dirty(TxShear) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -311,44 +299,23 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21, { } -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \fn QTransform::QTransform(const QMatrix &matrix) - \obsolete - - Constructs a matrix that is a copy of the given \a matrix. - Note that the \c m13, \c m23, and \c m33 elements are set to 0, 0, - and 1 respectively. - */ -QTransform::QTransform(const QMatrix &mtx) - : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true), - m_13(0), m_23(0), m_33(1) - , m_type(TxNone) - , m_dirty(TxShear) -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - , d(nullptr) -#endif -{ -} -#endif // QT_DEPRECATED_SINCE(5, 15) - /*! Returns the adjoint of this matrix. */ QTransform QTransform::adjoint() const { qreal h11, h12, h13, - h21, h22, h23, - h31, h32, h33; - h11 = affine._m22*m_33 - m_23*affine._dy; - h21 = m_23*affine._dx - affine._m21*m_33; - h31 = affine._m21*affine._dy - affine._m22*affine._dx; - h12 = m_13*affine._dy - affine._m12*m_33; - h22 = affine._m11*m_33 - m_13*affine._dx; - h32 = affine._m12*affine._dx - affine._m11*affine._dy; - h13 = affine._m12*m_23 - m_13*affine._m22; - h23 = m_13*affine._m21 - affine._m11*m_23; - h33 = affine._m11*affine._m22 - affine._m12*affine._m21; + h21, h22, h23, + h31, h32, h33; + h11 = m_matrix[1][1] * m_matrix[2][2] - m_matrix[1][2] * m_matrix[2][1]; + h21 = m_matrix[1][2] * m_matrix[2][0] - m_matrix[1][0] * m_matrix[2][2]; + h31 = m_matrix[1][0] * m_matrix[2][1] - m_matrix[1][1] * m_matrix[2][0]; + h12 = m_matrix[0][2] * m_matrix[2][1] - m_matrix[0][1] * m_matrix[2][2]; + h22 = m_matrix[0][0] * m_matrix[2][2] - m_matrix[0][2] * m_matrix[2][0]; + h32 = m_matrix[0][1] * m_matrix[2][0] - m_matrix[0][0] * m_matrix[2][1]; + h13 = m_matrix[0][1] * m_matrix[1][2] - m_matrix[0][2] * m_matrix[1][1]; + h23 = m_matrix[0][2] * m_matrix[1][0] - m_matrix[0][0] * m_matrix[1][2]; + h33 = m_matrix[0][0] * m_matrix[1][1] - m_matrix[0][1] * m_matrix[1][0]; return QTransform(h11, h12, h13, h21, h22, h23, @@ -360,9 +327,9 @@ QTransform QTransform::adjoint() const */ QTransform QTransform::transposed() const { - QTransform t(affine._m11, affine._m21, affine._dx, - affine._m12, affine._m22, affine._dy, - m_13, m_23, m_33, true); + QTransform t(m_matrix[0][0], m_matrix[1][0], m_matrix[2][0], + m_matrix[0][1], m_matrix[1][1], m_matrix[2][1], + m_matrix[0][2], m_matrix[1][2], m_matrix[2][2], true); return t; } @@ -385,23 +352,23 @@ QTransform QTransform::inverted(bool *invertible) const case TxNone: break; case TxTranslate: - invert.affine._dx = -affine._dx; - invert.affine._dy = -affine._dy; + invert.m_matrix[2][0] = -m_matrix[2][0]; + invert.m_matrix[2][1] = -m_matrix[2][1]; break; case TxScale: - inv = !qFuzzyIsNull(affine._m11); - inv &= !qFuzzyIsNull(affine._m22); + inv = !qFuzzyIsNull(m_matrix[0][0]); + inv &= !qFuzzyIsNull(m_matrix[1][1]); if (inv) { - invert.affine._m11 = 1. / affine._m11; - invert.affine._m22 = 1. / affine._m22; - invert.affine._dx = -affine._dx * invert.affine._m11; - invert.affine._dy = -affine._dy * invert.affine._m22; + invert.m_matrix[0][0] = 1. / m_matrix[0][0]; + invert.m_matrix[1][1] = 1. / m_matrix[1][1]; + invert.m_matrix[2][0] = -m_matrix[2][0] * invert.m_matrix[0][0]; + invert.m_matrix[2][1] = -m_matrix[2][1] * invert.m_matrix[1][1]; } break; - case TxRotate: - case TxShear: - invert.affine = affine.inverted(&inv); - break; +// case TxRotate: +// case TxShear: +// invert.affine = affine.inverted(&inv); +// break; default: // general case qreal det = determinant(); @@ -442,24 +409,24 @@ QTransform &QTransform::translate(qreal dx, qreal dy) switch(inline_type()) { case TxNone: - affine._dx = dx; - affine._dy = dy; + m_matrix[2][0] = dx; + m_matrix[2][1] = dy; break; case TxTranslate: - affine._dx += dx; - affine._dy += dy; + m_matrix[2][0] += dx; + m_matrix[2][1] += dy; break; case TxScale: - affine._dx += dx*affine._m11; - affine._dy += dy*affine._m22; + m_matrix[2][0] += dx * m_matrix[0][0]; + m_matrix[2][1] += dy * m_matrix[1][1]; break; case TxProject: - m_33 += dx*m_13 + dy*m_23; + m_matrix[2][2] += dx * m_matrix[0][2] + dy * m_matrix[1][2]; Q_FALLTHROUGH(); case TxShear: case TxRotate: - affine._dx += dx*affine._m11 + dy*affine._m21; - affine._dy += dy*affine._m22 + dx*affine._m12; + m_matrix[2][0] += dx * m_matrix[0][0] + dy * m_matrix[1][0]; + m_matrix[2][1] += dy * m_matrix[1][1] + dx * m_matrix[0][1]; break; } if (m_dirty < TxTranslate) @@ -511,21 +478,21 @@ QTransform & QTransform::scale(qreal sx, qreal sy) switch(inline_type()) { case TxNone: case TxTranslate: - affine._m11 = sx; - affine._m22 = sy; + m_matrix[0][0] = sx; + m_matrix[1][1] = sy; break; case TxProject: - m_13 *= sx; - m_23 *= sy; + m_matrix[0][2] *= sx; + m_matrix[1][2] *= sy; Q_FALLTHROUGH(); case TxRotate: case TxShear: - affine._m12 *= sx; - affine._m21 *= sy; + m_matrix[0][1] *= sx; + m_matrix[1][0] *= sy; Q_FALLTHROUGH(); case TxScale: - affine._m11 *= sx; - affine._m22 *= sy; + m_matrix[0][0] *= sx; + m_matrix[1][1] *= sy; break; } if (m_dirty < TxScale) @@ -577,28 +544,30 @@ QTransform & QTransform::shear(qreal sh, qreal sv) switch(inline_type()) { case TxNone: case TxTranslate: - affine._m12 = sv; - affine._m21 = sh; + m_matrix[0][1] = sv; + m_matrix[1][0] = sh; break; case TxScale: - affine._m12 = sv*affine._m22; - affine._m21 = sh*affine._m11; + m_matrix[0][1] = sv*m_matrix[1][1]; + m_matrix[1][0] = sh*m_matrix[0][0]; break; case TxProject: { - qreal tm13 = sv*m_23; - qreal tm23 = sh*m_13; - m_13 += tm13; - m_23 += tm23; + qreal tm13 = sv * m_matrix[1][2]; + qreal tm23 = sh * m_matrix[0][2]; + m_matrix[0][2] += tm13; + m_matrix[1][2] += tm23; } Q_FALLTHROUGH(); case TxRotate: case TxShear: { - qreal tm11 = sv*affine._m21; - qreal tm22 = sh*affine._m12; - qreal tm12 = sv*affine._m22; - qreal tm21 = sh*affine._m11; - affine._m11 += tm11; affine._m12 += tm12; - affine._m21 += tm21; affine._m22 += tm22; + qreal tm11 = sv * m_matrix[1][0]; + qreal tm22 = sh * m_matrix[0][1]; + qreal tm12 = sv * m_matrix[1][1]; + qreal tm21 = sh * m_matrix[0][0]; + m_matrix[0][0] += tm11; + m_matrix[0][1] += tm12; + m_matrix[1][0] += tm21; + m_matrix[1][1] += tm22; break; } } @@ -653,35 +622,39 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) switch(inline_type()) { case TxNone: case TxTranslate: - affine._m11 = cosa; - affine._m12 = sina; - affine._m21 = -sina; - affine._m22 = cosa; + m_matrix[0][0] = cosa; + m_matrix[0][1] = sina; + m_matrix[1][0] = -sina; + m_matrix[1][1] = cosa; break; case TxScale: { - qreal tm11 = cosa*affine._m11; - qreal tm12 = sina*affine._m22; - qreal tm21 = -sina*affine._m11; - qreal tm22 = cosa*affine._m22; - affine._m11 = tm11; affine._m12 = tm12; - affine._m21 = tm21; affine._m22 = tm22; + qreal tm11 = cosa * m_matrix[0][0]; + qreal tm12 = sina * m_matrix[1][1]; + qreal tm21 = -sina * m_matrix[0][0]; + qreal tm22 = cosa * m_matrix[1][1]; + m_matrix[0][0] = tm11; + m_matrix[0][1] = tm12; + m_matrix[1][0] = tm21; + m_matrix[1][1] = tm22; break; } case TxProject: { - qreal tm13 = cosa*m_13 + sina*m_23; - qreal tm23 = -sina*m_13 + cosa*m_23; - m_13 = tm13; - m_23 = tm23; + qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2]; + qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2]; + m_matrix[0][2] = tm13; + m_matrix[1][2] = tm23; Q_FALLTHROUGH(); } case TxRotate: case TxShear: { - qreal tm11 = cosa*affine._m11 + sina*affine._m21; - qreal tm12 = cosa*affine._m12 + sina*affine._m22; - qreal tm21 = -sina*affine._m11 + cosa*affine._m21; - qreal tm22 = -sina*affine._m12 + cosa*affine._m22; - affine._m11 = tm11; affine._m12 = tm12; - affine._m21 = tm21; affine._m22 = tm22; + qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0]; + qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1]; + qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0]; + qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1]; + m_matrix[0][0] = tm11; + m_matrix[0][1] = tm12; + m_matrix[1][0] = tm21; + m_matrix[1][1] = tm22; break; } } @@ -690,11 +663,11 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis) } else { QTransform result; if (axis == Qt::YAxis) { - result.affine._m11 = cosa; - result.m_13 = -sina * inv_dist_to_plane; + result.m_matrix[0][0] = cosa; + result.m_matrix[0][2] = -sina * inv_dist_to_plane; } else { - result.affine._m22 = cosa; - result.m_23 = -sina * inv_dist_to_plane; + result.m_matrix[1][1] = cosa; + result.m_matrix[1][2] = -sina * inv_dist_to_plane; } result.m_type = TxProject; *this = result * *this; @@ -732,35 +705,39 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) switch(inline_type()) { case TxNone: case TxTranslate: - affine._m11 = cosa; - affine._m12 = sina; - affine._m21 = -sina; - affine._m22 = cosa; + m_matrix[0][0] = cosa; + m_matrix[0][1] = sina; + m_matrix[1][0] = -sina; + m_matrix[1][1] = cosa; break; case TxScale: { - qreal tm11 = cosa*affine._m11; - qreal tm12 = sina*affine._m22; - qreal tm21 = -sina*affine._m11; - qreal tm22 = cosa*affine._m22; - affine._m11 = tm11; affine._m12 = tm12; - affine._m21 = tm21; affine._m22 = tm22; + qreal tm11 = cosa * m_matrix[0][0]; + qreal tm12 = sina * m_matrix[1][1]; + qreal tm21 = -sina * m_matrix[0][0]; + qreal tm22 = cosa * m_matrix[1][1]; + m_matrix[0][0] = tm11; + m_matrix[0][1] = tm12; + m_matrix[1][0] = tm21; + m_matrix[1][1] = tm22; break; } case TxProject: { - qreal tm13 = cosa*m_13 + sina*m_23; - qreal tm23 = -sina*m_13 + cosa*m_23; - m_13 = tm13; - m_23 = tm23; + qreal tm13 = cosa * m_matrix[0][2] + sina * m_matrix[1][2]; + qreal tm23 = -sina * m_matrix[0][2] + cosa * m_matrix[1][2]; + m_matrix[0][2] = tm13; + m_matrix[1][2] = tm23; Q_FALLTHROUGH(); } case TxRotate: case TxShear: { - qreal tm11 = cosa*affine._m11 + sina*affine._m21; - qreal tm12 = cosa*affine._m12 + sina*affine._m22; - qreal tm21 = -sina*affine._m11 + cosa*affine._m21; - qreal tm22 = -sina*affine._m12 + cosa*affine._m22; - affine._m11 = tm11; affine._m12 = tm12; - affine._m21 = tm21; affine._m22 = tm22; + qreal tm11 = cosa * m_matrix[0][0] + sina * m_matrix[1][0]; + qreal tm12 = cosa * m_matrix[0][1] + sina * m_matrix[1][1]; + qreal tm21 = -sina * m_matrix[0][0] + cosa * m_matrix[1][0]; + qreal tm22 = -sina * m_matrix[0][1] + cosa * m_matrix[1][1]; + m_matrix[0][0] = tm11; + m_matrix[0][1] = tm12; + m_matrix[1][0] = tm21; + m_matrix[1][1] = tm22; break; } } @@ -769,11 +746,11 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) } else { QTransform result; if (axis == Qt::YAxis) { - result.affine._m11 = cosa; - result.m_13 = -sina * inv_dist_to_plane; + result.m_matrix[0][0] = cosa; + result.m_matrix[0][2] = -sina * inv_dist_to_plane; } else { - result.affine._m22 = cosa; - result.m_23 = -sina * inv_dist_to_plane; + result.m_matrix[1][1] = cosa; + result.m_matrix[1][2] = -sina * inv_dist_to_plane; } result.m_type = TxProject; *this = result * *this; @@ -788,15 +765,15 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis) */ bool QTransform::operator==(const QTransform &o) const { - return affine._m11 == o.affine._m11 && - affine._m12 == o.affine._m12 && - affine._m21 == o.affine._m21 && - affine._m22 == o.affine._m22 && - affine._dx == o.affine._dx && - affine._dy == o.affine._dy && - m_13 == o.m_13 && - m_23 == o.m_23 && - m_33 == o.m_33; + return m_matrix[0][0] == o.m_matrix[0][0] && + m_matrix[0][1] == o.m_matrix[0][1] && + m_matrix[1][0] == o.m_matrix[1][0] && + m_matrix[1][1] == o.m_matrix[1][1] && + m_matrix[2][0] == o.m_matrix[2][0] && + m_matrix[2][1] == o.m_matrix[2][1] && + m_matrix[0][2] == o.m_matrix[0][2] && + m_matrix[1][2] == o.m_matrix[1][2] && + m_matrix[2][2] == o.m_matrix[2][2]; } /*! @@ -854,56 +831,59 @@ QTransform & QTransform::operator*=(const QTransform &o) case TxNone: break; case TxTranslate: - affine._dx += o.affine._dx; - affine._dy += o.affine._dy; + m_matrix[2][0] += o.m_matrix[2][0]; + m_matrix[2][1] += o.m_matrix[2][1]; break; case TxScale: { - qreal m11 = affine._m11*o.affine._m11; - qreal m22 = affine._m22*o.affine._m22; + qreal m11 = m_matrix[0][0] * o.m_matrix[0][0]; + qreal m22 = m_matrix[1][1] * o.m_matrix[1][1]; - qreal m31 = affine._dx*o.affine._m11 + o.affine._dx; - qreal m32 = affine._dy*o.affine._m22 + o.affine._dy; + qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + o.m_matrix[2][0]; + qreal m32 = m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1]; - affine._m11 = m11; - affine._m22 = m22; - affine._dx = m31; affine._dy = m32; + m_matrix[0][0] = m11; + m_matrix[1][1] = m22; + m_matrix[2][0] = m31; m_matrix[2][1] = m32; break; } case TxRotate: case TxShear: { - qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21; - qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22; + qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0]; + qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1]; - qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21; - qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22; + qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0]; + qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1]; - qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + o.affine._dx; - qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + o.affine._dy; + qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + o.m_matrix[2][0]; + qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + o.m_matrix[2][1]; - affine._m11 = m11; affine._m12 = m12; - affine._m21 = m21; affine._m22 = m22; - affine._dx = m31; affine._dy = m32; + m_matrix[0][0] = m11; + m_matrix[0][1] = m12; + m_matrix[1][0] = m21; + m_matrix[1][1] = m22; + m_matrix[2][0] = m31; + m_matrix[2][1] = m32; break; } case TxProject: { - qreal m11 = affine._m11*o.affine._m11 + affine._m12*o.affine._m21 + m_13*o.affine._dx; - qreal m12 = affine._m11*o.affine._m12 + affine._m12*o.affine._m22 + m_13*o.affine._dy; - qreal m13 = affine._m11*o.m_13 + affine._m12*o.m_23 + m_13*o.m_33; + qreal m11 = m_matrix[0][0] * o.m_matrix[0][0] + m_matrix[0][1] * o.m_matrix[1][0] + m_matrix[0][2] * o.m_matrix[2][0]; + qreal m12 = m_matrix[0][0] * o.m_matrix[0][1] + m_matrix[0][1] * o.m_matrix[1][1] + m_matrix[0][2] * o.m_matrix[2][1]; + qreal m13 = m_matrix[0][0] * o.m_matrix[0][2] + m_matrix[0][1] * o.m_matrix[1][2] + m_matrix[0][2] * o.m_matrix[2][2]; - qreal m21 = affine._m21*o.affine._m11 + affine._m22*o.affine._m21 + m_23*o.affine._dx; - qreal m22 = affine._m21*o.affine._m12 + affine._m22*o.affine._m22 + m_23*o.affine._dy; - qreal m23 = affine._m21*o.m_13 + affine._m22*o.m_23 + m_23*o.m_33; + qreal m21 = m_matrix[1][0] * o.m_matrix[0][0] + m_matrix[1][1] * o.m_matrix[1][0] + m_matrix[1][2] * o.m_matrix[2][0]; + qreal m22 = m_matrix[1][0] * o.m_matrix[0][1] + m_matrix[1][1] * o.m_matrix[1][1] + m_matrix[1][2] * o.m_matrix[2][1]; + qreal m23 = m_matrix[1][0] * o.m_matrix[0][2] + m_matrix[1][1] * o.m_matrix[1][2] + m_matrix[1][2] * o.m_matrix[2][2]; - qreal m31 = affine._dx*o.affine._m11 + affine._dy*o.affine._m21 + m_33*o.affine._dx; - qreal m32 = affine._dx*o.affine._m12 + affine._dy*o.affine._m22 + m_33*o.affine._dy; - qreal m33 = affine._dx*o.m_13 + affine._dy*o.m_23 + m_33*o.m_33; + qreal m31 = m_matrix[2][0] * o.m_matrix[0][0] + m_matrix[2][1] * o.m_matrix[1][0] + m_matrix[2][2] * o.m_matrix[2][0]; + qreal m32 = m_matrix[2][0] * o.m_matrix[0][1] + m_matrix[2][1] * o.m_matrix[1][1] + m_matrix[2][2] * o.m_matrix[2][1]; + qreal m33 = m_matrix[2][0] * o.m_matrix[0][2] + m_matrix[2][1] * o.m_matrix[1][2] + m_matrix[2][2] * o.m_matrix[2][2]; - affine._m11 = m11; affine._m12 = m12; m_13 = m13; - affine._m21 = m21; affine._m22 = m22; m_23 = m23; - affine._dx = m31; affine._dy = m32; m_33 = m33; + m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; + m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; + m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; } } @@ -937,56 +917,57 @@ QTransform QTransform::operator*(const QTransform &m) const case TxNone: break; case TxTranslate: - t.affine._dx = affine._dx + m.affine._dx; - t.affine._dy += affine._dy + m.affine._dy; + t.m_matrix[2][0] = m_matrix[2][0] + m.m_matrix[2][0]; + t.m_matrix[2][1] = m_matrix[2][1] + m.m_matrix[2][1]; break; case TxScale: { - qreal m11 = affine._m11*m.affine._m11; - qreal m22 = affine._m22*m.affine._m22; + qreal m11 = m_matrix[0][0] * m.m_matrix[0][0]; + qreal m22 = m_matrix[1][1] * m.m_matrix[1][1]; - qreal m31 = affine._dx*m.affine._m11 + m.affine._dx; - qreal m32 = affine._dy*m.affine._m22 + m.affine._dy; + qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m.m_matrix[2][0]; + qreal m32 = m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1]; - t.affine._m11 = m11; - t.affine._m22 = m22; - t.affine._dx = m31; t.affine._dy = m32; + t.m_matrix[0][0] = m11; + t.m_matrix[1][1] = m22; + t.m_matrix[2][0] = m31; + t.m_matrix[2][1] = m32; break; } case TxRotate: case TxShear: { - qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21; - qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22; + qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0]; + qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1]; - qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21; - qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22; + qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0]; + qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1]; - qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx; - qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy; + qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m.m_matrix[2][0]; + qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m.m_matrix[2][1]; - t.affine._m11 = m11; t.affine._m12 = m12; - t.affine._m21 = m21; t.affine._m22 = m22; - t.affine._dx = m31; t.affine._dy = m32; + t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; + t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; + t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; break; } case TxProject: { - qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx; - qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy; - qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33; + qreal m11 = m_matrix[0][0] * m.m_matrix[0][0] + m_matrix[0][1] * m.m_matrix[1][0] + m_matrix[0][2] * m.m_matrix[2][0]; + qreal m12 = m_matrix[0][0] * m.m_matrix[0][1] + m_matrix[0][1] * m.m_matrix[1][1] + m_matrix[0][2] * m.m_matrix[2][1]; + qreal m13 = m_matrix[0][0] * m.m_matrix[0][2] + m_matrix[0][1] * m.m_matrix[1][2] + m_matrix[0][2] * m.m_matrix[2][2]; - qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx; - qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy; - qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33; + qreal m21 = m_matrix[1][0] * m.m_matrix[0][0] + m_matrix[1][1] * m.m_matrix[1][0] + m_matrix[1][2] * m.m_matrix[2][0]; + qreal m22 = m_matrix[1][0] * m.m_matrix[0][1] + m_matrix[1][1] * m.m_matrix[1][1] + m_matrix[1][2] * m.m_matrix[2][1]; + qreal m23 = m_matrix[1][0] * m.m_matrix[0][2] + m_matrix[1][1] * m.m_matrix[1][2] + m_matrix[1][2] * m.m_matrix[2][2]; - qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx; - qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy; - qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33; + qreal m31 = m_matrix[2][0] * m.m_matrix[0][0] + m_matrix[2][1] * m.m_matrix[1][0] + m_matrix[2][2] * m.m_matrix[2][0]; + qreal m32 = m_matrix[2][0] * m.m_matrix[0][1] + m_matrix[2][1] * m.m_matrix[1][1] + m_matrix[2][2] * m.m_matrix[2][1]; + qreal m33 = m_matrix[2][0] * m.m_matrix[0][2] + m_matrix[2][1] * m.m_matrix[1][2] + m_matrix[2][2] * m.m_matrix[2][2]; - t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13; - t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23; - t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33; + t.m_matrix[0][0] = m11; t.m_matrix[0][1] = m12; t.m_matrix[0][2] = m13; + t.m_matrix[1][0] = m21; t.m_matrix[1][1] = m22; t.m_matrix[1][2] = m23; + t.m_matrix[2][0] = m31; t.m_matrix[2][1] = m32; t.m_matrix[2][2] = m33; } } @@ -1034,15 +1015,15 @@ QTransform QTransform::operator*(const QTransform &m) const */ QTransform & QTransform::operator=(const QTransform &matrix) noexcept { - affine._m11 = matrix.affine._m11; - affine._m12 = matrix.affine._m12; - affine._m21 = matrix.affine._m21; - affine._m22 = matrix.affine._m22; - affine._dx = matrix.affine._dx; - affine._dy = matrix.affine._dy; - m_13 = matrix.m_13; - m_23 = matrix.m_23; - m_33 = matrix.m_33; + m_matrix[0][0] = matrix.m_matrix[0][0]; + m_matrix[0][1] = matrix.m_matrix[0][1]; + m_matrix[1][0] = matrix.m_matrix[1][0]; + m_matrix[1][1] = matrix.m_matrix[1][1]; + m_matrix[2][0] = matrix.m_matrix[2][0]; + m_matrix[2][1] = matrix.m_matrix[2][1]; + m_matrix[0][2] = matrix.m_matrix[0][2]; + m_matrix[1][2] = matrix.m_matrix[1][2]; + m_matrix[2][2] = matrix.m_matrix[2][2]; m_type = matrix.m_type; m_dirty = matrix.m_dirty; @@ -1060,8 +1041,8 @@ QTransform & QTransform::operator=(const QTransform &matrix) noexcept */ void QTransform::reset() { - affine._m11 = affine._m22 = m_33 = 1.0; - affine._m12 = m_13 = affine._m21 = m_23 = affine._dx = affine._dy = 0; + m_matrix[0][0] = m_matrix[1][1] = m_matrix[2][2] = 1.0; + m_matrix[0][1] = m_matrix[0][2] = m_matrix[1][0] = m_matrix[1][2] = m_matrix[2][0] = m_matrix[2][1] = 0; m_type = TxNone; m_dirty = TxNone; } @@ -1179,20 +1160,20 @@ QPoint QTransform::map(const QPoint &p) const y = fy; break; case TxTranslate: - x = fx + affine._dx; - y = fy + affine._dy; + x = fx + m_matrix[2][0]; + y = fy + m_matrix[2][1]; break; case TxScale: - x = affine._m11 * fx + affine._dx; - y = affine._m22 * fy + affine._dy; + x = m_matrix[0][0] * fx + m_matrix[2][0]; + y = m_matrix[1][1] * fy + m_matrix[2][1]; break; case TxRotate: case TxShear: case TxProject: - x = affine._m11 * fx + affine._m21 * fy + affine._dx; - y = affine._m12 * fx + affine._m22 * fy + affine._dy; + x = m_matrix[0][0] * fx + m_matrix[1][0] * fy + m_matrix[2][0]; + y = m_matrix[0][1] * fx + m_matrix[1][1] * fy + m_matrix[2][1]; if (t == TxProject) { - qreal w = 1./(m_13 * fx + m_23 * fy + m_33); + qreal w = 1./(m_matrix[0][2] * fx + m_matrix[1][2] * fy + m_matrix[2][2]); x *= w; y *= w; } @@ -1230,20 +1211,20 @@ QPointF QTransform::map(const QPointF &p) const y = fy; break; case TxTranslate: - x = fx + affine._dx; - y = fy + affine._dy; + x = fx + m_matrix[2][0]; + y = fy + m_matrix[2][1]; break; case TxScale: - x = affine._m11 * fx + affine._dx; - y = affine._m22 * fy + affine._dy; + x = m_matrix[0][0] * fx + m_matrix[2][0]; + y = m_matrix[1][1] * fy + m_matrix[2][1]; break; case TxRotate: case TxShear: case TxProject: - x = affine._m11 * fx + affine._m21 * fy + affine._dx; - y = affine._m12 * fx + affine._m22 * fy + affine._dy; + x = m_matrix[0][0] * fx + m_matrix[1][0] * fy + m_matrix[2][0]; + y = m_matrix[0][1] * fx + m_matrix[1][1] * fy + m_matrix[2][1]; if (t == TxProject) { - qreal w = 1./(m_13 * fx + m_23 * fy + m_33); + qreal w = 1./(m_matrix[0][2] * fx + m_matrix[1][2] * fy + m_matrix[2][2]); x *= w; y *= w; } @@ -1303,29 +1284,29 @@ QLine QTransform::map(const QLine &l) const y2 = fy2; break; case TxTranslate: - x1 = fx1 + affine._dx; - y1 = fy1 + affine._dy; - x2 = fx2 + affine._dx; - y2 = fy2 + affine._dy; + x1 = fx1 + m_matrix[2][0]; + y1 = fy1 + m_matrix[2][1]; + x2 = fx2 + m_matrix[2][0]; + y2 = fy2 + m_matrix[2][1]; break; case TxScale: - x1 = affine._m11 * fx1 + affine._dx; - y1 = affine._m22 * fy1 + affine._dy; - x2 = affine._m11 * fx2 + affine._dx; - y2 = affine._m22 * fy2 + affine._dy; + x1 = m_matrix[0][0] * fx1 + m_matrix[2][0]; + y1 = m_matrix[1][1] * fy1 + m_matrix[2][1]; + x2 = m_matrix[0][0] * fx2 + m_matrix[2][0]; + y2 = m_matrix[1][1] * fy2 + m_matrix[2][1]; break; case TxRotate: case TxShear: case TxProject: - x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx; - y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy; - x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx; - y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy; + x1 = m_matrix[0][0] * fx1 + m_matrix[1][0] * fy1 + m_matrix[2][0]; + y1 = m_matrix[0][1] * fx1 + m_matrix[1][1] * fy1 + m_matrix[2][1]; + x2 = m_matrix[0][0] * fx2 + m_matrix[1][0] * fy2 + m_matrix[2][0]; + y2 = m_matrix[0][1] * fx2 + m_matrix[1][1] * fy2 + m_matrix[2][1]; if (t == TxProject) { - qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33); + qreal w = 1./(m_matrix[0][2] * fx1 + m_matrix[1][2] * fy1 + m_matrix[2][2]); x1 *= w; y1 *= w; - w = 1./(m_13 * fx2 + m_23 * fy2 + m_33); + w = 1./(m_matrix[0][2] * fx2 + m_matrix[1][2] * fy2 + m_matrix[2][2]); x2 *= w; y2 *= w; } @@ -1362,29 +1343,29 @@ QLineF QTransform::map(const QLineF &l) const y2 = fy2; break; case TxTranslate: - x1 = fx1 + affine._dx; - y1 = fy1 + affine._dy; - x2 = fx2 + affine._dx; - y2 = fy2 + affine._dy; + x1 = fx1 + m_matrix[2][0]; + y1 = fy1 + m_matrix[2][1]; + x2 = fx2 + m_matrix[2][0]; + y2 = fy2 + m_matrix[2][1]; break; case TxScale: - x1 = affine._m11 * fx1 + affine._dx; - y1 = affine._m22 * fy1 + affine._dy; - x2 = affine._m11 * fx2 + affine._dx; - y2 = affine._m22 * fy2 + affine._dy; + x1 = m_matrix[0][0] * fx1 + m_matrix[2][0]; + y1 = m_matrix[1][1] * fy1 + m_matrix[2][1]; + x2 = m_matrix[0][0] * fx2 + m_matrix[2][0]; + y2 = m_matrix[1][1] * fy2 + m_matrix[2][1]; break; case TxRotate: case TxShear: case TxProject: - x1 = affine._m11 * fx1 + affine._m21 * fy1 + affine._dx; - y1 = affine._m12 * fx1 + affine._m22 * fy1 + affine._dy; - x2 = affine._m11 * fx2 + affine._m21 * fy2 + affine._dx; - y2 = affine._m12 * fx2 + affine._m22 * fy2 + affine._dy; + x1 = m_matrix[0][0] * fx1 + m_matrix[1][0] * fy1 + m_matrix[2][0]; + y1 = m_matrix[0][1] * fx1 + m_matrix[1][1] * fy1 + m_matrix[2][1]; + x2 = m_matrix[0][0] * fx2 + m_matrix[1][0] * fy2 + m_matrix[2][0]; + y2 = m_matrix[0][1] * fx2 + m_matrix[1][1] * fy2 + m_matrix[2][1]; if (t == TxProject) { - qreal w = 1./(m_13 * fx1 + m_23 * fy1 + m_33); + qreal w = 1./(m_matrix[0][2] * fx1 + m_matrix[1][2] * fy1 + m_matrix[2][2]); x1 *= w; y1 *= w; - w = 1./(m_13 * fx2 + m_23 * fy2 + m_33); + w = 1./(m_matrix[0][2] * fx2 + m_matrix[1][2] * fy2 + m_matrix[2][2]); x2 *= w; y2 *= w; } @@ -1445,7 +1426,7 @@ QPolygonF QTransform::map(const QPolygonF &a) const { TransformationType t = inline_type(); if (t <= TxTranslate) - return a.translated(affine._dx, affine._dy); + return a.translated(m_matrix[2][0], m_matrix[2][1]); if (t >= QTransform::TxProject) return mapProjective(*this, a); @@ -1475,7 +1456,7 @@ QPolygon QTransform::map(const QPolygon &a) const { TransformationType t = inline_type(); if (t <= TxTranslate) - return a.translated(qRound(affine._dx), qRound(affine._dy)); + return a.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1])); if (t >= QTransform::TxProject) return mapProjective(*this, QPolygonF(a)).toPolygon(); @@ -1524,7 +1505,7 @@ QRegion QTransform::map(const QRegion &r) const if (t == TxTranslate) { QRegion copy(r); - copy.translate(qRound(affine._dx), qRound(affine._dy)); + copy.translate(qRound(m_matrix[2][0]), qRound(m_matrix[2][1])); return copy; } @@ -1547,7 +1528,7 @@ QRegion QTransform::map(const QRegion &r) const } QPainterPath p = map(qt_regionToPath(r)); - return p.toFillPolygon(QTransform()).toPolygon(); + return p.toFillPolygon().toPolygon(); } struct QHomogeneousCoordinate @@ -1703,7 +1684,7 @@ QPainterPath QTransform::map(const QPainterPath &path) const QPainterPath copy = path; if (t == TxTranslate) { - copy.translate(affine._dx, affine._dy); + copy.translate(m_matrix[2][0], m_matrix[2][1]); } else { copy.detach(); // Full xform @@ -1743,10 +1724,10 @@ QPolygon QTransform::mapToPolygon(const QRect &rect) const QPolygon a(4); qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 }; if (t <= TxScale) { - x[0] = affine._m11*rect.x() + affine._dx; - y[0] = affine._m22*rect.y() + affine._dy; - qreal w = affine._m11*rect.width(); - qreal h = affine._m22*rect.height(); + x[0] = m_matrix[0][0]*rect.x() + m_matrix[2][0]; + y[0] = m_matrix[1][1]*rect.y() + m_matrix[2][1]; + qreal w = m_matrix[0][0]*rect.width(); + qreal h = m_matrix[1][1]*rect.height(); if (w < 0) { w = -w; x[0] -= w; @@ -1903,9 +1884,9 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33) { - affine._m11 = m11; affine._m12 = m12; m_13 = m13; - affine._m21 = m21; affine._m22 = m22; m_23 = m23; - affine._dx = m31; affine._dy = m32; m_33 = m33; + m_matrix[0][0] = m11; m_matrix[0][1] = m12; m_matrix[0][2] = m13; + m_matrix[1][0] = m21; m_matrix[1][1] = m22; m_matrix[1][2] = m23; + m_matrix[2][0] = m31; m_matrix[2][1] = m32; m_matrix[2][2] = m33; m_type = TxNone; m_dirty = TxProject; } @@ -1922,13 +1903,13 @@ QRect QTransform::mapRect(const QRect &rect) const { TransformationType t = inline_type(); if (t <= TxTranslate) - return rect.translated(qRound(affine._dx), qRound(affine._dy)); + return rect.translated(qRound(m_matrix[2][0]), qRound(m_matrix[2][1])); if (t <= TxScale) { - int x = qRound(affine._m11*rect.x() + affine._dx); - int y = qRound(affine._m22*rect.y() + affine._dy); - int w = qRound(affine._m11*rect.width()); - int h = qRound(affine._m22*rect.height()); + int x = qRound(m_matrix[0][0] * rect.x() + m_matrix[2][0]); + int y = qRound(m_matrix[1][1] * rect.y() + m_matrix[2][1]); + int w = qRound(m_matrix[0][0] * rect.width()); + int h = qRound(m_matrix[1][1] * rect.height()); if (w < 0) { w = -w; x -= w; @@ -1992,13 +1973,13 @@ QRectF QTransform::mapRect(const QRectF &rect) const { TransformationType t = inline_type(); if (t <= TxTranslate) - return rect.translated(affine._dx, affine._dy); + return rect.translated(m_matrix[2][0], m_matrix[2][1]); if (t <= TxScale) { - qreal x = affine._m11*rect.x() + affine._dx; - qreal y = affine._m22*rect.y() + affine._dy; - qreal w = affine._m11*rect.width(); - qreal h = affine._m22*rect.height(); + qreal x = m_matrix[0][0] * rect.x() + m_matrix[2][0]; + qreal y = m_matrix[1][1] * rect.y() + m_matrix[2][1]; + qreal w = m_matrix[0][0] * rect.width(); + qreal h = m_matrix[1][1] * rect.height(); if (w < 0) { w = -w; x -= w; @@ -2085,20 +2066,6 @@ void QTransform::map(int x, int y, int *tx, int *ty) const *ty = qRound(fy); } -#if QT_DEPRECATED_SINCE(5, 15) -/*! - \obsolete - Returns the QTransform as an affine matrix. - - \warning If a perspective transformation has been specified, - then the conversion will cause loss of data. -*/ -const QMatrix &QTransform::toAffine() const -{ - return affine; -} -#endif // QT_DEPRECATED_SINCE(5, 15) - /*! Returns the transformation type of this matrix. @@ -2118,15 +2085,15 @@ QTransform::TransformationType QTransform::type() const switch (static_cast<TransformationType>(m_dirty)) { case TxProject: - if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) { + if (!qFuzzyIsNull(m_matrix[0][2]) || !qFuzzyIsNull(m_matrix[1][2]) || !qFuzzyIsNull(m_matrix[2][2] - 1)) { m_type = TxProject; break; } Q_FALLTHROUGH(); case TxShear: case TxRotate: - if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) { - const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22; + if (!qFuzzyIsNull(m_matrix[0][1]) || !qFuzzyIsNull(m_matrix[1][0])) { + const qreal dot = m_matrix[0][0] * m_matrix[0][1] + m_matrix[1][0] * m_matrix[1][1]; if (qFuzzyIsNull(dot)) m_type = TxRotate; else @@ -2135,13 +2102,13 @@ QTransform::TransformationType QTransform::type() const } Q_FALLTHROUGH(); case TxScale: - if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) { + if (!qFuzzyIsNull(m_matrix[0][0] - 1) || !qFuzzyIsNull(m_matrix[1][1] - 1)) { m_type = TxScale; break; } Q_FALLTHROUGH(); case TxTranslate: - if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) { + if (!qFuzzyIsNull(m_matrix[2][0]) || !qFuzzyIsNull(m_matrix[2][1])) { m_type = TxTranslate; break; } @@ -2390,4 +2357,50 @@ bool qt_scaleForTransform(const QTransform &transform, qreal *scale) } } +QDataStream & operator>>(QDataStream &s, QTransform::Affine &m) +{ + if (s.version() == 1) { + float m11, m12, m21, m22, dx, dy; + s >> m11; s >> m12; s >> m21; s >> m22; s >> dx; s >> dy; + + m.m_matrix[0][0] = m11; + m.m_matrix[0][1] = m12; + m.m_matrix[1][0] = m21; + m.m_matrix[1][1] = m22; + m.m_matrix[2][0] = dx; + m.m_matrix[2][1] = dy; + } else { + s >> m.m_matrix[0][0]; + s >> m.m_matrix[0][1]; + s >> m.m_matrix[1][0]; + s >> m.m_matrix[1][1]; + s >> m.m_matrix[2][0]; + s >> m.m_matrix[2][1]; + } + m.m_matrix[0][2] = 0; + m.m_matrix[1][2] = 0; + m.m_matrix[2][2] = 1; + return s; +} + +QDataStream &operator<<(QDataStream &s, const QTransform::Affine &m) +{ + if (s.version() == 1) { + s << (float)m.m_matrix[0][0] + << (float)m.m_matrix[0][1] + << (float)m.m_matrix[1][0] + << (float)m.m_matrix[1][1] + << (float)m.m_matrix[2][0] + << (float)m.m_matrix[2][1]; + } else { + s << m.m_matrix[0][0] + << m.m_matrix[0][1] + << m.m_matrix[1][0] + << m.m_matrix[1][1] + << m.m_matrix[2][0] + << m.m_matrix[2][1]; + } + return s; +} + QT_END_NAMESPACE diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 485caa5140..351f2b2e4e 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -40,7 +40,6 @@ #define QTRANSFORM_H #include <QtGui/qtguiglobal.h> -#include <QtGui/qmatrix.h> #include <QtGui/qpainterpath.h> #include <QtGui/qpolygon.h> #include <QtGui/qregion.h> @@ -66,16 +65,13 @@ public: TxProject = 0x10 }; - inline explicit QTransform(Qt::Initialization) : affine(Qt::Uninitialized) {} + inline explicit QTransform(Qt::Initialization) {} QTransform(); QTransform(qreal h11, qreal h12, qreal h13, qreal h21, qreal h22, qreal h23, qreal h31, qreal h32, qreal h33 = 1.0); QTransform(qreal h11, qreal h12, qreal h21, qreal h22, qreal dx, qreal dy); -#if QT_DEPRECATED_SINCE(5, 15) - explicit QTransform(const QMatrix &mtx); -#endif // QT_DEPRECATED_SINCE(5, 15) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove; the compiler-generated ones are fine! @@ -160,10 +156,6 @@ public: void map(int x, int y, int *tx, int *ty) const; void map(qreal x, qreal y, qreal *tx, qreal *ty) const; -#if QT_DEPRECATED_SINCE(5, 15) - const QMatrix &toAffine() const; -#endif // QT_DEPRECATED_SINCE(5, 15) - QTransform &operator*=(qreal div); QTransform &operator/=(qreal div); QTransform &operator+=(qreal div); @@ -173,11 +165,20 @@ public: static QTransform fromScale(qreal dx, qreal dy); private: + struct Affine { + qreal (& m_matrix)[3][3]; + }; + +public: + auto asAffineMatrix() { return Affine { m_matrix }; } + friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &s, Affine &m); + friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &s, const Affine &m); + +private: inline QTransform(qreal h11, qreal h12, qreal h13, qreal h21, qreal h22, qreal h23, qreal h31, qreal h32, qreal h33, bool) - : affine(h11, h12, h21, h22, h31, h32, true) - , m_13(h13), m_23(h23), m_33(h33) + : m_matrix{ {h11, h12, h13}, {h21, h22, h23}, {h31, h32, h33} } , m_type(TxNone) , m_dirty(TxProject) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -186,8 +187,7 @@ private: { } inline QTransform(bool) - : affine(true) - , m_13(0), m_23(0), m_33(1) + : m_matrix{ {1, 0, 0}, {0, 1, 0}, {0, 0, 1} } , m_type(TxNone) , m_dirty(TxNone) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -196,10 +196,7 @@ private: { } inline TransformationType inline_type() const; - QMatrix affine; - qreal m_13; - qreal m_23; - qreal m_33; + qreal m_matrix[3][3]; mutable uint m_type : 5; mutable uint m_dirty : 5; @@ -250,8 +247,9 @@ inline bool QTransform::isTranslating() const inline qreal QTransform::determinant() const { - return affine._m11*(m_33*affine._m22-affine._dy*m_23) - - affine._m21*(m_33*affine._m12-affine._dy*m_13)+affine._dx*(m_23*affine._m12-affine._m22*m_13); + return m_matrix[0][0] * (m_matrix[2][2] * m_matrix[1][1] - m_matrix[2][1] * m_matrix[1][2]) - + m_matrix[1][0] * (m_matrix[2][2] * m_matrix[0][1] - m_matrix[2][1] * m_matrix[0][2]) + + m_matrix[2][0] * (m_matrix[1][2] * m_matrix[0][1] - m_matrix[1][1] * m_matrix[0][2]); } #if QT_DEPRECATED_SINCE(5, 13) inline qreal QTransform::det() const @@ -261,47 +259,47 @@ inline qreal QTransform::det() const #endif inline qreal QTransform::m11() const { - return affine._m11; + return m_matrix[0][0]; } inline qreal QTransform::m12() const { - return affine._m12; + return m_matrix[0][1]; } inline qreal QTransform::m13() const { - return m_13; + return m_matrix[0][2]; } inline qreal QTransform::m21() const { - return affine._m21; + return m_matrix[1][0]; } inline qreal QTransform::m22() const { - return affine._m22; + return m_matrix[1][1]; } inline qreal QTransform::m23() const { - return m_23; + return m_matrix[1][2]; } inline qreal QTransform::m31() const { - return affine._dx; + return m_matrix[2][0]; } inline qreal QTransform::m32() const { - return affine._dy; + return m_matrix[2][1]; } inline qreal QTransform::m33() const { - return m_33; + return m_matrix[2][2]; } inline qreal QTransform::dx() const { - return affine._dx; + return m_matrix[2][0]; } inline qreal QTransform::dy() const { - return affine._dy; + return m_matrix[2][1]; } QT_WARNING_PUSH @@ -313,15 +311,15 @@ inline QTransform &QTransform::operator*=(qreal num) { if (num == 1.) return *this; - affine._m11 *= num; - affine._m12 *= num; - m_13 *= num; - affine._m21 *= num; - affine._m22 *= num; - m_23 *= num; - affine._dx *= num; - affine._dy *= num; - m_33 *= num; + m_matrix[0][0] *= num; + m_matrix[0][1] *= num; + m_matrix[0][2] *= num; + m_matrix[1][0] *= num; + m_matrix[1][1] *= num; + m_matrix[1][2] *= num; + m_matrix[2][0] *= num; + m_matrix[2][1] *= num; + m_matrix[2][2] *= num; if (m_dirty < TxScale) m_dirty = TxScale; return *this; @@ -337,15 +335,15 @@ inline QTransform &QTransform::operator+=(qreal num) { if (num == 0) return *this; - affine._m11 += num; - affine._m12 += num; - m_13 += num; - affine._m21 += num; - affine._m22 += num; - m_23 += num; - affine._dx += num; - affine._dy += num; - m_33 += num; + m_matrix[0][0] += num; + m_matrix[0][1] += num; + m_matrix[0][2] += num; + m_matrix[1][0] += num; + m_matrix[1][1] += num; + m_matrix[1][2] += num; + m_matrix[2][0] += num; + m_matrix[2][1] += num; + m_matrix[2][2] += num; m_dirty = TxProject; return *this; } @@ -353,15 +351,15 @@ inline QTransform &QTransform::operator-=(qreal num) { if (num == 0) return *this; - affine._m11 -= num; - affine._m12 -= num; - m_13 -= num; - affine._m21 -= num; - affine._m22 -= num; - m_23 -= num; - affine._dx -= num; - affine._dy -= num; - m_33 -= num; + m_matrix[0][0] -= num; + m_matrix[0][1] -= num; + m_matrix[0][2] -= num; + m_matrix[1][0] -= num; + m_matrix[1][1] -= num; + m_matrix[1][2] -= num; + m_matrix[2][0] -= num; + m_matrix[2][1] -= num; + m_matrix[2][2] -= num; m_dirty = TxProject; return *this; } |