diff options
Diffstat (limited to 'src/gui')
23 files changed, 487 insertions, 1670 deletions
diff --git a/src/gui/.prev_CMakeLists.txt b/src/gui/.prev_CMakeLists.txt index 3a218eb3a6..f8529ba650 100644 --- a/src/gui/.prev_CMakeLists.txt +++ b/src/gui/.prev_CMakeLists.txt @@ -262,7 +262,6 @@ qt_extend_target(Gui CONDITION QT_FEATURE_opengl opengl/qopenglfunctions.cpp opengl/qopenglfunctions.h opengl/qopenglprogrambinarycache.cpp opengl/qopenglprogrambinarycache_p.h opengl/qopenglshaderprogram.cpp opengl/qopenglshaderprogram.h - opengl/qopengltextureblitter.cpp opengl/qopengltextureblitter.h opengl/qopenglversionfunctions.cpp opengl/qopenglversionfunctions.h opengl/qopenglversionfunctionsfactory.cpp opengl/qopenglversionfunctionsfactory_p.h opengl/qopenglvertexarrayobject.cpp opengl/qopenglvertexarrayobject.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index c93b43fdf2..ab1b3884cb 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -344,7 +344,6 @@ qt_extend_target(Gui CONDITION QT_FEATURE_opengl opengl/qopenglfunctions.cpp opengl/qopenglfunctions.h opengl/qopenglprogrambinarycache.cpp opengl/qopenglprogrambinarycache_p.h opengl/qopenglshaderprogram.cpp opengl/qopenglshaderprogram.h - opengl/qopengltextureblitter.cpp opengl/qopengltextureblitter.h opengl/qopenglversionfunctions.cpp opengl/qopenglversionfunctions.h opengl/qopenglversionfunctionsfactory.cpp opengl/qopenglversionfunctionsfactory_p.h opengl/qopenglvertexarrayobject.cpp opengl/qopenglvertexarrayobject.h diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index a789e65284..6edcd7befa 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -619,7 +619,6 @@ QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectH QAccessible::ActivationObserver::~ActivationObserver() { - // must be empty until ### Qt 6 } /*! @@ -1334,7 +1333,6 @@ QColor QAccessibleInterface::backgroundColor() const */ QAccessibleEvent::~QAccessibleEvent() { - // must be empty until ### Qt 6 } /*! \fn QAccessible::Event QAccessibleEvent::type() const @@ -1414,7 +1412,6 @@ QAccessible::Id QAccessibleEvent::uniqueId() const */ QAccessibleValueChangeEvent::~QAccessibleValueChangeEvent() { - // must be empty until ### Qt 6 } /*! @@ -1458,7 +1455,6 @@ QAccessibleValueChangeEvent::~QAccessibleValueChangeEvent() */ QAccessibleStateChangeEvent::~QAccessibleStateChangeEvent() { - // must be empty until ### Qt 6 } /*! @@ -1538,7 +1534,6 @@ QAccessibleStateChangeEvent::~QAccessibleStateChangeEvent() */ QAccessibleTableModelChangeEvent::~QAccessibleTableModelChangeEvent() { - // must be empty until ### Qt 6 } /*! \class QAccessibleTextCursorEvent @@ -1567,7 +1562,6 @@ QAccessibleTableModelChangeEvent::~QAccessibleTableModelChangeEvent() */ QAccessibleTextCursorEvent::~QAccessibleTextCursorEvent() { - // must be empty until ### Qt 6 } @@ -1608,7 +1602,6 @@ QAccessibleTextCursorEvent::~QAccessibleTextCursorEvent() */ QAccessibleTextInsertEvent::~QAccessibleTextInsertEvent() { - // must be empty until ### Qt 6 } @@ -1651,7 +1644,6 @@ QAccessibleTextInsertEvent::~QAccessibleTextInsertEvent() */ QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent() { - // must be empty until ### Qt 6 } /*! @@ -1713,7 +1705,6 @@ QAccessibleTextRemoveEvent::~QAccessibleTextRemoveEvent() */ QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent() { - // must be empty until ### Qt 6 } @@ -1748,7 +1739,6 @@ QAccessibleTextUpdateEvent::~QAccessibleTextUpdateEvent() */ QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent() { - // must be empty until ### Qt 6 } @@ -1978,7 +1968,6 @@ QDebug operator<<(QDebug d, const QAccessibleEvent &ev) */ QAccessibleTextInterface::~QAccessibleTextInterface() { - // must be empty until ### Qt 6 } /*! @@ -2367,7 +2356,6 @@ QString QAccessibleTextInterface::textAtOffset(int offset, QAccessible::TextBoun */ QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface() { - // must be empty until ### Qt 6 } /*! @@ -2412,7 +2400,6 @@ QAccessibleEditableTextInterface::~QAccessibleEditableTextInterface() */ QAccessibleValueInterface::~QAccessibleValueInterface() { - // must be empty until ### Qt 6 } /*! @@ -2476,7 +2463,6 @@ QAccessibleValueInterface::~QAccessibleValueInterface() */ QAccessibleImageInterface::~QAccessibleImageInterface() { - // must be empty until ### Qt 6 } /*! @@ -2496,7 +2482,6 @@ QAccessibleImageInterface::~QAccessibleImageInterface() */ QAccessibleTableCellInterface::~QAccessibleTableCellInterface() { - // must be empty until ### Qt 6 } /*! @@ -2564,7 +2549,6 @@ QAccessibleTableCellInterface::~QAccessibleTableCellInterface() */ QAccessibleTableInterface::~QAccessibleTableInterface() { - // must be empty until ### Qt 6 } /*! @@ -2740,7 +2724,6 @@ QAccessibleTableInterface::~QAccessibleTableInterface() */ QAccessibleActionInterface::~QAccessibleActionInterface() { - // must be empty until ### Qt 6 } /*! diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 2b4ed24ba4..aac73e8bc2 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -557,6 +557,11 @@ qt_feature("directwrite1" PRIVATE CONDITION libs.dwrite_1 OR FIXME EMIT_IF WIN32 ) +qt_feature("directwrite3" PRIVATE + LABEL "DirectWrite 3" + CONDITION QT_FEATURE_directwrite1 AND libs.dwrite_3 OR FIXME + EMIT_IF WIN32 +) qt_feature("directwrite2" PRIVATE LABEL "DirectWrite 2" CONDITION QT_FEATURE_directwrite1 AND libs.dwrite_2 OR FIXME diff --git a/src/gui/configure.json b/src/gui/configure.json index 469473af22..8bc3e8dc0c 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -189,6 +189,20 @@ "-ldwrite" ] }, + "dwrite_3": { + "label": "DirectWrite 3", + "test": { + "main": [ + "IUnknown *factory = 0;", + "DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3),", + " &factory);" + ] + }, + "headers": "dwrite_3.h", + "sources": [ + "-ldwrite" + ] + }, "drm": { "label": "KMS", "test": { @@ -1145,6 +1159,12 @@ "condition": "libs.dwrite_1", "output": [ "privateFeature" ] }, + "directwrite3": { + "label": "DirectWrite 3", + "emitIf": "config.win32", + "condition": "features.directwrite1 && libs.dwrite_3", + "output": [ "privateFeature" ] + }, "directwrite2": { "label": "DirectWrite 2", "emitIf": "config.win32", diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 663573b640..c2dac71e0d 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2063,7 +2063,6 @@ QInputMethodEvent::QInputMethodEvent(const QInputMethodEvent &other) QInputMethodEvent::~QInputMethodEvent() { - // must be empty until ### Qt 6 } /*! diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index a723ca6e7f..1f8d8d21e9 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -613,6 +613,13 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME \li \c {dpiawareness=[0|1|2} Sets the DPI awareness of the process (see \l{High DPI Displays}, since Qt 5.4). \li \c {fontengine=freetype}, uses the FreeType font engine. + \li \c {fontengine=directwrite}, uses the experimental DirectWrite + font database and defaults to using the DirectWrite font + engine (which is otherwise only used for some font types + or font properties.) This affects font selection and aims + to provide font naming more consistent with other platforms, + but does not support all font formats, such as Postscript + Type-1 or Microsoft FNT fonts. \li \c {menus=[native|none]}, controls the use of native menus. Native menus are implemented using Win32 API and are simpler than diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 6915433aed..ae5a98e832 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -623,7 +623,6 @@ bool QOpenGLContext::create() */ void QOpenGLContext::destroy() { - deleteQGLContext(); Q_D(QOpenGLContext); if (d->platformGLContext) emit aboutToBeDestroyed(); @@ -1177,44 +1176,6 @@ QScreen *QOpenGLContext::screen() const } /*! - internal: Needs to have a pointer to qGLContext. But since this is in Qt GUI we can't - have any type information. - - \internal -*/ -void *QOpenGLContext::qGLContextHandle() const -{ - Q_D(const QOpenGLContext); - return d->qGLContextHandle; -} - -/*! - internal: If the delete function is specified QOpenGLContext "owns" - the passed context handle and will use the delete function to destroy it. - - \internal -*/ -void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *)) -{ - Q_D(QOpenGLContext); - d->qGLContextHandle = handle; - d->qGLContextDeleteFunction = qGLContextDeleteFunction; -} - -/*! - \internal -*/ -void QOpenGLContext::deleteQGLContext() -{ - Q_D(QOpenGLContext); - if (d->qGLContextDeleteFunction && d->qGLContextHandle) { - d->qGLContextDeleteFunction(d->qGLContextHandle); - d->qGLContextDeleteFunction = nullptr; - d->qGLContextHandle = nullptr; - } -} - -/*! Returns the platform-specific handle for the OpenGL implementation that is currently in use. (for example, a HMODULE on Windows) diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index f19dde465a..a96ea56d7b 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -218,8 +218,6 @@ Q_SIGNALS: void aboutToBeDestroyed(); private: - friend class QGLContext; - friend class QGLPixelBuffer; friend class QOpenGLContextResourceBase; friend class QOpenGLPaintDevice; friend class QOpenGLGlyphTexture; @@ -234,10 +232,6 @@ private: friend class QAbstractOpenGLFunctionsPrivate; friend class QOpenGLTexturePrivate; - void *qGLContextHandle() const; - void setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *)); - void deleteQGLContext(); - QOpenGLVersionFunctionsStorage* functionsBackendStorage() const; void insertExternalFunctions(QAbstractOpenGLFunctions *f); void removeExternalFunctions(QAbstractOpenGLFunctions *f); diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 7770b1ce02..d769f03fd3 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -197,9 +197,7 @@ class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QOpenGLContext) public: QOpenGLContextPrivate() - : qGLContextHandle(nullptr) - , qGLContextDeleteFunction(nullptr) - , platformGLContext(nullptr) + : platformGLContext(nullptr) , shareContext(nullptr) , shareGroup(nullptr) , screen(nullptr) @@ -228,9 +226,6 @@ public: mutable QOpenGLVersionFunctionsStorage versionFunctionsStorage; mutable QSet<QAbstractOpenGLFunctions *> externalVersionFunctions; - void *qGLContextHandle; - void (*qGLContextDeleteFunction)(void *handle); - QSurfaceFormat requestedFormat; QPlatformOpenGLContext *platformGLContext; QOpenGLContext *shareContext; diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.h b/src/gui/kernel/qplatformgraphicsbufferhelper.h index bfe61713d4..36afd4877b 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.h +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.h @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE namespace QPlatformGraphicsBufferHelper { - bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, const QRect &rect = QRect()); + Q_GUI_EXPORT bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, const QRect &rect = QRect()); bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = nullptr, bool *premultipliedB = nullptr, const QRect &rect = QRect()); } diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri index f1e2019417..8d91a9e4b2 100644 --- a/src/gui/opengl/opengl.pri +++ b/src/gui/opengl/opengl.pri @@ -16,7 +16,6 @@ qtConfig(opengl) { opengl/qopenglversionfunctions.h \ opengl/qopenglversionfunctionsfactory_p.h \ opengl/qopenglvertexarrayobject.h \ - opengl/qopengltextureblitter.h \ opengl/qopenglextrafunctions.h \ opengl/qopenglprogrambinarycache_p.h @@ -28,7 +27,6 @@ qtConfig(opengl) { opengl/qopenglversionfunctions.cpp \ opengl/qopenglversionfunctionsfactory.cpp \ opengl/qopenglvertexarrayobject.cpp \ - opengl/qopengltextureblitter.cpp \ opengl/qopenglprogrambinarycache.cpp !qtConfig(opengles2) { diff --git a/src/gui/opengl/qopengltextureblitter.cpp b/src/gui/opengl/qopengltextureblitter.cpp deleted file mode 100644 index b709f2f639..0000000000 --- a/src/gui/opengl/qopengltextureblitter.cpp +++ /dev/null @@ -1,682 +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 "qopengltextureblitter.h" - -#include <QtGui/QOpenGLBuffer> -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QOpenGLVertexArrayObject> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> - -#ifndef GL_TEXTURE_EXTERNAL_OES -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#endif - -QT_BEGIN_NAMESPACE - -/*! - \class QOpenGLTextureBlitter - \brief The QOpenGLTextureBlitter class provides a convenient way to draw textured quads via OpenGL. - \since 5.8 - \ingroup painting-3D - \inmodule QtGui - - Drawing textured quads, in order to get the contents of a texture - onto the screen, is a common operation when developing 2D user - interfaces. QOpenGLTextureBlitter provides a convenience class to - avoid repeating vertex data, shader sources, buffer and program - management and matrix calculations. - - For example, a QOpenGLWidget subclass can do the following to draw - the contents rendered into a framebuffer at the pixel position \c{(x, y)}: - - \code - void OpenGLWidget::initializeGL() - { - m_blitter.create(); - m_fbo = new QOpenGLFramebufferObject(size); - } - - void OpenGLWidget::paintGL() - { - m_fbo->bind(); - // update offscreen content - m_fbo->release(); - - m_blitter.bind(); - const QRect targetRect(QPoint(x, y), m_fbo->size()); - const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), m_fbo->size())); - m_blitter.blit(m_fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft); - m_blitter.release(); - } - \endcode - - The blitter implements GLSL shaders both for GLSL 1.00 (suitable - for OpenGL (ES) 2.x and compatibility profiles of newer OpenGL - versions) and version 150 (suitable for core profile contexts with - OpenGL 3.2 and newer). - */ - -static const char vertex_shader150[] = - "#version 150 core\n" - "in vec3 vertexCoord;" - "in vec2 textureCoord;" - "out vec2 uv;" - "uniform mat4 vertexTransform;" - "uniform mat3 textureTransform;" - "void main() {" - " uv = (textureTransform * vec3(textureCoord,1.0)).xy;" - " gl_Position = vertexTransform * vec4(vertexCoord,1.0);" - "}"; - -static const char fragment_shader150[] = - "#version 150 core\n" - "in vec2 uv;" - "out vec4 fragcolor;" - "uniform sampler2D textureSampler;" - "uniform bool swizzle;" - "uniform float opacity;" - "void main() {" - " vec4 tmpFragColor = texture(textureSampler, uv);" - " tmpFragColor.a *= opacity;" - " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;" - "}"; - -static const char vertex_shader[] = - "attribute highp vec3 vertexCoord;" - "attribute highp vec2 textureCoord;" - "varying highp vec2 uv;" - "uniform highp mat4 vertexTransform;" - "uniform highp mat3 textureTransform;" - "void main() {" - " uv = (textureTransform * vec3(textureCoord,1.0)).xy;" - " gl_Position = vertexTransform * vec4(vertexCoord,1.0);" - "}"; - -static const char fragment_shader[] = - "varying highp vec2 uv;" - "uniform sampler2D textureSampler;" - "uniform bool swizzle;" - "uniform highp float opacity;" - "void main() {" - " highp vec4 tmpFragColor = texture2D(textureSampler,uv);" - " tmpFragColor.a *= opacity;" - " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;" - "}"; - -static const char fragment_shader_external_oes[] = - "#extension GL_OES_EGL_image_external : require\n" - "varying highp vec2 uv;" - "uniform samplerExternalOES textureSampler;\n" - "uniform bool swizzle;" - "uniform highp float opacity;" - "void main() {" - " highp vec4 tmpFragColor = texture2D(textureSampler, uv);" - " tmpFragColor.a *= opacity;" - " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;" - "}"; - -static const GLfloat vertex_buffer_data[] = { - -1,-1, 0, - -1, 1, 0, - 1,-1, 0, - -1, 1, 0, - 1,-1, 0, - 1, 1, 0 -}; - -static const GLfloat texture_buffer_data[] = { - 0, 0, - 0, 1, - 1, 0, - 0, 1, - 1, 0, - 1, 1 -}; - -class TextureBinder -{ -public: - TextureBinder(GLenum target, GLuint textureId) : m_target(target) - { - QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, textureId); - } - ~TextureBinder() - { - QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, 0); - } - -private: - GLenum m_target; -}; - -class QOpenGLTextureBlitterPrivate -{ -public: - enum TextureMatrixUniform { - User, - Identity, - IdentityFlipped - }; - - enum ProgramIndex { - TEXTURE_2D, - TEXTURE_EXTERNAL_OES - }; - - QOpenGLTextureBlitterPrivate() : - swizzle(false), - opacity(1.0f), - vao(new QOpenGLVertexArrayObject), - currentTarget(TEXTURE_2D) - { } - - bool buildProgram(ProgramIndex idx, const char *vs, const char *fs); - - void blit(GLuint texture, const QMatrix4x4 &vertexTransform, const QMatrix3x3 &textureTransform); - void blit(GLuint texture, const QMatrix4x4 &vertexTransform, QOpenGLTextureBlitter::Origin origin); - - void prepareProgram(const QMatrix4x4 &vertexTransform); - - QOpenGLBuffer vertexBuffer; - QOpenGLBuffer textureBuffer; - struct Program { - Program() : - vertexCoordAttribPos(0), - vertexTransformUniformPos(0), - textureCoordAttribPos(0), - textureTransformUniformPos(0), - swizzleUniformPos(0), - opacityUniformPos(0), - swizzle(false), - opacity(0.0f), - textureMatrixUniformState(User) - { } - QScopedPointer<QOpenGLShaderProgram> glProgram; - GLuint vertexCoordAttribPos; - GLuint vertexTransformUniformPos; - GLuint textureCoordAttribPos; - GLuint textureTransformUniformPos; - GLuint swizzleUniformPos; - GLuint opacityUniformPos; - bool swizzle; - float opacity; - TextureMatrixUniform textureMatrixUniformState; - } programs[2]; - bool swizzle; - float opacity; - QScopedPointer<QOpenGLVertexArrayObject> vao; - GLenum currentTarget; -}; - -static inline QOpenGLTextureBlitterPrivate::ProgramIndex targetToProgramIndex(GLenum target) -{ - switch (target) { - case GL_TEXTURE_2D: - return QOpenGLTextureBlitterPrivate::TEXTURE_2D; - case GL_TEXTURE_EXTERNAL_OES: - return QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES; - default: - qWarning("Unsupported texture target 0x%x", target); - return QOpenGLTextureBlitterPrivate::TEXTURE_2D; - } -} - -void QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransform) -{ - Program *program = &programs[targetToProgramIndex(currentTarget)]; - - vertexBuffer.bind(); - program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0); - program->glProgram->enableAttributeArray(program->vertexCoordAttribPos); - vertexBuffer.release(); - - program->glProgram->setUniformValue(program->vertexTransformUniformPos, vertexTransform); - - textureBuffer.bind(); - program->glProgram->setAttributeBuffer(program->textureCoordAttribPos, GL_FLOAT, 0, 2, 0); - program->glProgram->enableAttributeArray(program->textureCoordAttribPos); - textureBuffer.release(); - - if (swizzle != program->swizzle) { - program->glProgram->setUniformValue(program->swizzleUniformPos, swizzle); - program->swizzle = swizzle; - } - - if (opacity != program->opacity) { - program->glProgram->setUniformValue(program->opacityUniformPos, opacity); - program->opacity = opacity; - } -} - -void QOpenGLTextureBlitterPrivate::blit(GLuint texture, - const QMatrix4x4 &vertexTransform, - const QMatrix3x3 &textureTransform) -{ - TextureBinder binder(currentTarget, texture); - prepareProgram(vertexTransform); - - Program *program = &programs[targetToProgramIndex(currentTarget)]; - program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform); - program->textureMatrixUniformState = User; - - QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6); -} - -void QOpenGLTextureBlitterPrivate::blit(GLuint texture, - const QMatrix4x4 &vertexTransform, - QOpenGLTextureBlitter::Origin origin) -{ - TextureBinder binder(currentTarget, texture); - prepareProgram(vertexTransform); - - Program *program = &programs[targetToProgramIndex(currentTarget)]; - if (origin == QOpenGLTextureBlitter::OriginTopLeft) { - if (program->textureMatrixUniformState != IdentityFlipped) { - QMatrix3x3 flipped; - flipped(1,1) = -1; - flipped(1,2) = 1; - program->glProgram->setUniformValue(program->textureTransformUniformPos, flipped); - program->textureMatrixUniformState = IdentityFlipped; - } - } else if (program->textureMatrixUniformState != Identity) { - program->glProgram->setUniformValue(program->textureTransformUniformPos, QMatrix3x3()); - program->textureMatrixUniformState = Identity; - } - - QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6); -} - -bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs, const char *fs) -{ - Program *p = &programs[idx]; - - p->glProgram.reset(new QOpenGLShaderProgram); - - p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vs); - p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fs); - p->glProgram->link(); - if (!p->glProgram->isLinked()) { - qWarning() << "Could not link shader program:\n" << p->glProgram->log(); - return false; - } - - p->glProgram->bind(); - - p->vertexCoordAttribPos = p->glProgram->attributeLocation("vertexCoord"); - p->vertexTransformUniformPos = p->glProgram->uniformLocation("vertexTransform"); - p->textureCoordAttribPos = p->glProgram->attributeLocation("textureCoord"); - p->textureTransformUniformPos = p->glProgram->uniformLocation("textureTransform"); - p->swizzleUniformPos = p->glProgram->uniformLocation("swizzle"); - p->opacityUniformPos = p->glProgram->uniformLocation("opacity"); - - p->glProgram->setUniformValue(p->swizzleUniformPos, false); - - // minmize state left set after a create() - p->glProgram->release(); - - return true; -} - -/*! - Constructs a new QOpenGLTextureBlitter instance. - - \note no graphics resources are initialized in the - constructor. This makes it safe to place plain - QOpenGLTextureBlitter members into classes because the actual - initialization that depends on the OpenGL context happens only in - create(). - */ -QOpenGLTextureBlitter::QOpenGLTextureBlitter() - : d_ptr(new QOpenGLTextureBlitterPrivate) -{ -} - -/*! - Destructs the instance. - - \note When the OpenGL context - or a context sharing resources - with it - that was current when calling create() is not current, - graphics resources will not be released. Therefore, it is - recommended to call destroy() manually instead of relying on the - destructor to perform OpenGL resource cleanup. - */ -QOpenGLTextureBlitter::~QOpenGLTextureBlitter() -{ - destroy(); -} - -/*! - Initializes the graphics resources used by the blitter. - - \return \c true if successful, \c false if there was a - failure. Failures can occur when there is no OpenGL context - current on the current thread, or when shader compilation fails - for some reason. - - \sa isCreated(), destroy() - */ -bool QOpenGLTextureBlitter::create() -{ - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - if (!currentContext) - return false; - - Q_D(QOpenGLTextureBlitter); - - if (d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram) - return true; - - QSurfaceFormat format = currentContext->format(); - if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) { - if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150)) - return false; - } else { - if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader)) - return false; - if (supportsExternalOESTarget()) - if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES, vertex_shader, fragment_shader_external_oes)) - return false; - } - - // Create and bind the VAO, if supported. - QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data()); - - d->vertexBuffer.create(); - d->vertexBuffer.bind(); - d->vertexBuffer.allocate(vertex_buffer_data, sizeof(vertex_buffer_data)); - d->vertexBuffer.release(); - - d->textureBuffer.create(); - d->textureBuffer.bind(); - d->textureBuffer.allocate(texture_buffer_data, sizeof(texture_buffer_data)); - d->textureBuffer.release(); - - return true; -} - -/*! - \return \c true if create() was called and succeeded. \c false otherwise. - - \sa create(), destroy() - */ -bool QOpenGLTextureBlitter::isCreated() const -{ - Q_D(const QOpenGLTextureBlitter); - return d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram; -} - -/*! - Frees all graphics resources held by the blitter. Assumes that - the OpenGL context, or another context sharing resources with it, - that was current on the thread when invoking create() is current. - - The function has no effect when the blitter is not in created state. - - \sa create() - */ -void QOpenGLTextureBlitter::destroy() -{ - if (!isCreated()) - return; - Q_D(QOpenGLTextureBlitter); - d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.reset(); - d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES].glProgram.reset(); - d->vertexBuffer.destroy(); - d->textureBuffer.destroy(); - d->vao.reset(); -} - -/*! - \return \c true when bind() accepts \c GL_TEXTURE_EXTERNAL_OES as - its target argument. - - \sa bind(), blit() - */ -bool QOpenGLTextureBlitter::supportsExternalOESTarget() const -{ - QOpenGLContext *ctx = QOpenGLContext::currentContext(); - return ctx && ctx->isOpenGLES() && ctx->hasExtension("GL_OES_EGL_image_external"); -} - -/*! - Binds the graphics resources used by the blitter. This must be - called before calling blit(). Code modifying the OpenGL state - should be avoided between the call to bind() and blit() because - otherwise conflicts may arise. - - \a target is the texture target for the source texture and must be - either \c GL_TEXTURE_2D or \c GL_OES_EGL_image_external. - - \sa release(), blit() - */ -void QOpenGLTextureBlitter::bind(GLenum target) -{ - Q_D(QOpenGLTextureBlitter); - - if (d->vao->isCreated()) - d->vao->bind(); - - d->currentTarget = target; - QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(target)]; - p->glProgram->bind(); - - d->vertexBuffer.bind(); - p->glProgram->setAttributeBuffer(p->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0); - p->glProgram->enableAttributeArray(p->vertexCoordAttribPos); - d->vertexBuffer.release(); - - d->textureBuffer.bind(); - p->glProgram->setAttributeBuffer(p->textureCoordAttribPos, GL_FLOAT, 0, 2, 0); - p->glProgram->enableAttributeArray(p->textureCoordAttribPos); - d->textureBuffer.release(); -} - -/*! - Unbinds the graphics resources used by the blitter. - - \sa bind() - */ -void QOpenGLTextureBlitter::release() -{ - Q_D(QOpenGLTextureBlitter); - d->programs[targetToProgramIndex(d->currentTarget)].glProgram->release(); - if (d->vao->isCreated()) - d->vao->release(); -} - -/*! - Sets whether swizzling is enabled for the red and blue color channels to - \a swizzle. An BGRA to RGBA conversion (occurring in the shader on - the GPU, instead of a slow CPU-side transformation) can be useful - when the source texture contains data from a QImage with a format - like QImage::Format_ARGB32 which maps to BGRA on little endian - systems. - - By default the red-blue swizzle is disabled since this is what a - texture attached to an framebuffer object or a texture based on a - byte ordered QImage format (like QImage::Format_RGBA8888) needs. - */ -void QOpenGLTextureBlitter::setRedBlueSwizzle(bool swizzle) -{ - Q_D(QOpenGLTextureBlitter); - d->swizzle = swizzle; -} - -/*! - Changes the opacity to \a opacity. The default opacity is 1.0. - - \note the blitter does not alter the blend state. It is up to the - caller of blit() to ensure the correct blend settings are active. - - */ -void QOpenGLTextureBlitter::setOpacity(float opacity) -{ - Q_D(QOpenGLTextureBlitter); - d->opacity = opacity; -} - -/*! - \enum QOpenGLTextureBlitter::Origin - - \value OriginBottomLeft Indicates that the data in the texture - follows the OpenGL convention of coordinate systems, meaning Y is - running from bottom to top. - - \value OriginTopLeft Indicates that the data in the texture has Y - running from top to bottom, which is typical with regular, - unflipped image data. - - \sa blit() - */ - -/*! - Performs the blit with the source texture \a texture. - - \a targetTransform specifies the transformation applied. This is - usually generated by the targetTransform() helper function. - - \a sourceOrigin specifies if the image data needs flipping. When - \a texture corresponds to a texture attached to an FBO pass - OriginBottomLeft. On the other hand, when \a texture is based on - unflipped image data, pass OriginTopLeft. This is more efficient - than using QImage::mirrored(). - - \sa targetTransform(), Origin, bind() - */ -void QOpenGLTextureBlitter::blit(GLuint texture, - const QMatrix4x4 &targetTransform, - Origin sourceOrigin) -{ - Q_D(QOpenGLTextureBlitter); - d->blit(texture,targetTransform, sourceOrigin); -} - -/*! - Performs the blit with the source texture \a texture. - - \a targetTransform specifies the transformation applied. This is - usually generated by the targetTransform() helper function. - - \a sourceTransform specifies the transformation applied to the - source. This allows using only a sub-rect of the source - texture. This is usually generated by the sourceTransform() helper - function. - - \sa sourceTransform(), targetTransform(), Origin, bind() - */ -void QOpenGLTextureBlitter::blit(GLuint texture, - const QMatrix4x4 &targetTransform, - const QMatrix3x3 &sourceTransform) -{ - Q_D(QOpenGLTextureBlitter); - d->blit(texture, targetTransform, sourceTransform); -} - -/*! - Calculates a target transform suitable for blit(). - - \a target is the target rectangle in pixels. \a viewport describes - the source dimensions and will in most cases be set to (0, 0, - image width, image height). - - For unscaled output the size of \a target and \a viewport should - match. - - \sa blit() - */ -QMatrix4x4 QOpenGLTextureBlitter::targetTransform(const QRectF &target, - const QRect &viewport) -{ - qreal x_scale = target.width() / viewport.width(); - qreal y_scale = target.height() / viewport.height(); - - const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft(); - qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2); - qreal y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2); - - QMatrix4x4 matrix; - matrix(0,3) = x_translate; - matrix(1,3) = y_translate; - - matrix(0,0) = x_scale; - matrix(1,1) = y_scale; - - return matrix; -} - -/*! - Calculates a 3x3 matrix suitable as the input to blit(). This is - used when only a part of the texture is to be used in the blit. - - \a subTexture is the desired source rectangle in pixels, \a - textureSize is the full width and height of the texture data. \a - origin specifies the orientation of the image data when it comes - to the Y axis. - - \sa blit(), Origin - */ -QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(const QRectF &subTexture, - const QSize &textureSize, - Origin origin) -{ - qreal x_scale = subTexture.width() / textureSize.width(); - qreal y_scale = subTexture.height() / textureSize.height(); - - const QPointF topLeft = subTexture.topLeft(); - qreal x_translate = topLeft.x() / textureSize.width(); - qreal y_translate = topLeft.y() / textureSize.height(); - - if (origin == OriginTopLeft) { - y_scale = -y_scale; - y_translate = 1 - y_translate; - } - - QMatrix3x3 matrix; - matrix(0,2) = x_translate; - matrix(1,2) = y_translate; - - matrix(0,0) = x_scale; - matrix(1,1) = y_scale; - - return matrix; -} - -QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengltextureblitter.h b/src/gui/opengl/qopengltextureblitter.h deleted file mode 100644 index 2f7c6b1a0a..0000000000 --- a/src/gui/opengl/qopengltextureblitter.h +++ /dev/null @@ -1,94 +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 QOPENGLTEXTUREBLITTER_H -#define QOPENGLTEXTUREBLITTER_H - -#include <QtGui/qtguiglobal.h> - -#ifndef QT_NO_OPENGL - -#include <QtGui/qopengl.h> -#include <QtGui/QMatrix3x3> -#include <QtGui/QMatrix4x4> - -QT_BEGIN_NAMESPACE - -class QOpenGLTextureBlitterPrivate; - -class Q_GUI_EXPORT QOpenGLTextureBlitter -{ -public: - QOpenGLTextureBlitter(); - ~QOpenGLTextureBlitter(); - - enum Origin { - OriginBottomLeft, - OriginTopLeft - }; - - bool create(); - bool isCreated() const; - void destroy(); - - bool supportsExternalOESTarget() const; - - void bind(GLenum target = GL_TEXTURE_2D); - void release(); - - void setRedBlueSwizzle(bool swizzle); - void setOpacity(float opacity); - - void blit(GLuint texture, const QMatrix4x4 &targetTransform, Origin sourceOrigin); - void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform); - - static QMatrix4x4 targetTransform(const QRectF &target, const QRect &viewport); - static QMatrix3x3 sourceTransform(const QRectF &subTexture, const QSize &textureSize, Origin origin); - -private: - Q_DISABLE_COPY(QOpenGLTextureBlitter) - Q_DECLARE_PRIVATE(QOpenGLTextureBlitter) - QScopedPointer<QOpenGLTextureBlitterPrivate> d_ptr; -}; - -QT_END_NAMESPACE - -#endif - -#endif //QOPENGLTEXTUREBLITTER_H diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index 3a01248c57..9a719b3059 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -90,7 +90,7 @@ public: void setStyle(Qt::BrushStyle); #if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("Use transform()") inline const QMatrix &matrix() const; + QT_DEPRECATED_X("Use transform()") inline QMatrix matrix() const; QT_DEPRECATED_X("Use setTransform()") void setMatrix(const QMatrix &mat); #endif // QT_DEPRECATED_SINCE(5, 15) @@ -161,7 +161,7 @@ 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(); } +inline 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/qpainter.cpp b/src/gui/painting/qpainter.cpp index 390147463d..6867b34b46 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) { @@ -2953,7 +2958,7 @@ void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) {Coordinate System} */ -const QMatrix &QPainter::worldMatrix() const +QMatrix QPainter::worldMatrix() const { Q_D(const QPainter); if (!d->engine) { @@ -2984,7 +2989,7 @@ void QPainter::setMatrix(const QMatrix &matrix, bool combine) \sa worldTransform() */ -const QMatrix &QPainter::matrix() const +QMatrix QPainter::matrix() const { QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED @@ -3030,7 +3035,7 @@ QMatrix QPainter::combinedMatrix() const \sa worldMatrix(), QPaintEngine::hasFeature(), */ -const QMatrix &QPainter::deviceMatrix() const +QMatrix QPainter::deviceMatrix() const { Q_D(const QPainter); if (!d->engine) { @@ -5607,40 +5612,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 +5670,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 +5858,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 +6371,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) diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 77c6504d2e..205cd1dd2b 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -240,9 +240,9 @@ public: QT_DEPRECATED_X("Use setTransform() instead") void setMatrix(const QMatrix &matrix, bool combine = false); QT_DEPRECATED_X("Use transform() instead") - const QMatrix &matrix() const; + QMatrix matrix() const; QT_DEPRECATED_X("Use deviceTransform() instead") - const QMatrix &deviceMatrix() const; + QMatrix deviceMatrix() const; QT_DEPRECATED_X("Use resetTransform() instead") void resetMatrix(); #endif @@ -256,7 +256,7 @@ public: QT_DEPRECATED_X("Use setWorldTransform() instead") void setWorldMatrix(const QMatrix &matrix, bool combine = false); QT_DEPRECATED_X("Use worldTransform() instead") - const QMatrix &worldMatrix() const; + QMatrix worldMatrix() const; QT_DEPRECATED_X("Use combinedTransform() instead") QMatrix combinedMatrix() const; QT_DEPRECATED_X("Use setWorldMatrixEnabled() instead") 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/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/qtransform.cpp b/src/gui/painting/qtransform.cpp index 9d8bb0c3e2..7bc10df68e 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -76,20 +76,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; \ @@ -261,8 +261,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 +281,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 +299,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) @@ -321,8 +318,7 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21, 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_matrix{ {mtx._m11, mtx._m12, 0}, {mtx._m21, mtx._m22, 0}, {mtx._dx, mtx._dy, 1} } , m_type(TxNone) , m_dirty(TxShear) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -338,17 +334,17 @@ QTransform::QTransform(const QMatrix &mtx) 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 +356,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 +381,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 +438,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 +507,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 +573,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 +651,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 +692,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 +734,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 +775,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 +794,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 +860,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 +946,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 +1044,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 +1070,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 +1189,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 +1240,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 +1313,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 +1372,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 +1455,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 +1485,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 +1534,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; } @@ -1703,7 +1713,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 +1753,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 +1913,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 +1932,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 +2002,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; @@ -2093,9 +2103,11 @@ void QTransform::map(int x, int y, int *tx, int *ty) const \warning If a perspective transformation has been specified, then the conversion will cause loss of data. */ -const QMatrix &QTransform::toAffine() const +QMatrix QTransform::toAffine() const { - return affine; + return QMatrix(m_matrix[0][0], m_matrix[0][1], + m_matrix[1][0], m_matrix[1][1], + m_matrix[2][0], m_matrix[2][1]); } #endif // QT_DEPRECATED_SINCE(5, 15) @@ -2118,15 +2130,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 +2147,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; } diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index 485caa5140..ac84599f2e 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -66,7 +66,7 @@ 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, @@ -161,7 +161,7 @@ public: void map(qreal x, qreal y, qreal *tx, qreal *ty) const; #if QT_DEPRECATED_SINCE(5, 15) - const QMatrix &toAffine() const; + QMatrix toAffine() const; #endif // QT_DEPRECATED_SINCE(5, 15) QTransform &operator*=(qreal div); @@ -176,8 +176,7 @@ 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 +185,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 +194,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 +245,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 +257,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 +309,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 +333,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 +349,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; } diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index 8528f59844..bfce38797a 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -53,7 +53,6 @@ QAbstractTextDocumentLayoutPrivate::~QAbstractTextDocumentLayoutPrivate() QTextObjectInterface::~QTextObjectInterface() { - // must be empty until ### Qt 6 } /*! |