diff options
Diffstat (limited to 'src/gui')
41 files changed, 429 insertions, 2070 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index e5b290ae1f..cb89fccc2d 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -257,7 +257,8 @@ QT_BEGIN_NAMESPACE \value SelectionWithin Several changes to a selection has occurred in an item view. \value SoundPlayed A sound has been played by an object - \value StateChanged The QAccessible::State of an object has changed. + \omitvalue StateChanged The QAccessible::State of an object has changed. + This value is used internally for the QAccessibleStateChangeEvent. \value TableCaptionChanged A table caption has been changed. \value TableColumnDescriptionChanged The description of a table column, typically found in the column's header, has been changed. @@ -308,6 +309,7 @@ QT_BEGIN_NAMESPACE \value ColumnHeader A header for a column of data. \value ComboBox A list of choices that the user can select from. \value Cursor An object that represents the mouse cursor. + \value Desktop The object represents the desktop or workspace. \value Dial An object that represents a dial or knob. \value Dialog A dialog box. \value Document A document window, usually in an MDI environment. @@ -345,6 +347,7 @@ QT_BEGIN_NAMESPACE \value StaticText Static text, such as labels for other widgets. \value StatusBar A status bar. \value Table A table representing data in a grid of rows and columns. + \value Terminal A terminal or command line interface. \value TitleBar The title bar caption of a window. \value ToolBar A tool bar, which groups widgets that the user accesses frequently. \value ToolTip A tool tip which provides information about other objects. @@ -694,9 +697,32 @@ void QAccessible::updateAccessibility(const QAccessibleEvent &event) This class should be created on the stack and used as parameter for \l QAccessible::updateAccessibility(). + \sa QAccessibleStateChangedEvent */ /*! + \class QAccessibleStateChangedEvent + \brief This subclass of QAccessibleEvent is used to inform about state changes. + \internal + + \ingroup accessibility + \inmodule QtGui + + This class should be created on the stack and used as parameter for + \l QAccessible::updateAccessibility(). + In addition to the regular \l QAccessibleEvent it contains details about which states + changed. + \sa QAccessibleEvent +*/ + +/*! + \fn QAccessibleStateChangeEvent::changedStates() const + All states that have changed are set to true. This does not reflect the state of the object, + but indicates which states are changed. + Use the \l QAccessibleInterface::state() function to get the current state. + */ + +/*! Returns the QAccessibleInterface associated with the event. The caller of this function takes ownership of the returned interface. diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 6ad1bb9da9..e8a5cf8bad 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -292,6 +292,7 @@ public: // Additional Qt roles where enum value does not map directly to MSAA: LayeredPane = 0x0000003F, Terminal = 0x00000040, + Desktop = 0x00000041, UserRole = 0x0000ffff }; @@ -436,6 +437,9 @@ public: Q_ASSERT(obj); } + virtual ~QAccessibleEvent() + {} + QAccessible::Event type() const { return m_type; } QObject *object() const { return m_object; } int child() const { return m_child; } @@ -448,6 +452,21 @@ private: int m_child; }; +class Q_GUI_EXPORT QAccessibleStateChangeEvent :public QAccessibleEvent +{ +public: + inline QAccessibleStateChangeEvent(QAccessible::State state, QObject *obj, int chld = -1) + : QAccessibleEvent(QAccessible::StateChanged, obj, chld), m_changedStates(state) + {} + + QAccessible::State changedStates() const { + return m_changedStates; + } + +private: + QAccessible::State m_changedStates; +}; + #define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface" Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid) diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index b84c484f74..61e46ebf04 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -70,24 +70,6 @@ namespace QAccessible2 LineBoundary, NoBoundary }; - - enum TableModelChangeType { - TableModelChangeInsert, - TableModelChangeDelete, - TableModelChangeUpdate - }; - - struct TableModelChange { - int firstColumn; - int firstRow; - int lastColumn; - int lastRow; - TableModelChangeType type; - - TableModelChange() - : firstColumn(0), firstRow(0), lastColumn(0), lastRow(0), type(TableModelChangeUpdate) - {} - }; } class Q_GUI_EXPORT QAccessibleTextInterface @@ -230,19 +212,8 @@ public: virtual bool unselectRow(int row) = 0; // Unselects one column, leaving other selected columns selected (if any). virtual bool unselectColumn(int column) = 0; - // Returns the type and extents describing how a table changed. - virtual QAccessible2::TableModelChange modelChange() const = 0; protected: - // These functions are called when the model changes. - virtual void modelReset() = 0; - virtual void rowsInserted(const QModelIndex &parent, int first, int last) = 0; - virtual void rowsRemoved(const QModelIndex &parent, int first, int last) = 0; - virtual void columnsInserted(const QModelIndex &parent, int first, int last) = 0; - virtual void columnsRemoved(const QModelIndex &parent, int first, int last) = 0; - virtual void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row) = 0; - virtual void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column) = 0; - friend class QAbstractItemView; friend class QAbstractItemViewPrivate; }; diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri deleted file mode 100644 index e4a2bbef75..0000000000 --- a/src/gui/egl/egl.pri +++ /dev/null @@ -1,26 +0,0 @@ -contains(QT_CONFIG, egl): { - CONFIG += egl - - HEADERS += \ - egl/qegl_p.h \ - egl/qeglcontext_p.h \ - egl/qeglproperties_p.h - - SOURCES += \ - egl/qegl.cpp \ - egl/qeglproperties.cpp - unix { - !isEmpty(QMAKE_INCDIR_EGL){ - INCLUDEPATH += $$QMAKE_INCDIR_EGL - } - !isEmpty(QMAKE_LIBDIR_EGL){ - for(p, QMAKE_LIBDIR_EGL) { - exists($$p):LIBS += -L$$p - } - } - - !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL - } - - SOURCES += egl/qegl_qpa.cpp -} diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp deleted file mode 100644 index 067886cf5a..0000000000 --- a/src/gui/egl/qegl.cpp +++ /dev/null @@ -1,751 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui/qpaintdevice.h> -#include <QtGui/qpixmap.h> -#include <QtGui/qwidget.h> -#include <QtCore/qatomic.h> -#include <QtCore/qdebug.h> - -#include "qegl_p.h" -#include "qeglcontext_p.h" - - -QT_BEGIN_NAMESPACE - - -/* - QEglContextTracker is used to track the EGL contexts that we - create internally in Qt, so that we can call eglTerminate() to - free additional EGL resources when the last context is destroyed. -*/ - -class QEglContextTracker -{ -public: - static void ref() { contexts.ref(); } - static void deref() { - if (!contexts.deref()) { - eglTerminate(QEgl::display()); - displayOpen = 0; - } - } - static void setDisplayOpened() { displayOpen = 1; } - static bool displayOpened() { return displayOpen; } - -private: - static QBasicAtomicInt contexts; - static QBasicAtomicInt displayOpen; -}; - -QBasicAtomicInt QEglContextTracker::contexts = Q_BASIC_ATOMIC_INITIALIZER(0); -QBasicAtomicInt QEglContextTracker::displayOpen = Q_BASIC_ATOMIC_INITIALIZER(0); - -// Current GL and VG contexts. These are used to determine if -// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent(). -// If a background thread modifies the value, the worst that will -// happen is a redundant eglMakeCurrent() in the foreground thread. -static QEglContext * volatile currentGLContext = 0; -static QEglContext * volatile currentVGContext = 0; - -QEglContext::QEglContext() - : apiType(QEgl::OpenGL) - , ctx(EGL_NO_CONTEXT) - , cfg(QEGL_NO_CONFIG) - , currentSurface(EGL_NO_SURFACE) - , current(false) - , ownsContext(true) - , sharing(false) -{ - QEglContextTracker::ref(); -} - -QEglContext::~QEglContext() -{ - destroyContext(); - - if (currentGLContext == this) - currentGLContext = 0; - if (currentVGContext == this) - currentVGContext = 0; - QEglContextTracker::deref(); -} - -bool QEglContext::isValid() const -{ - return (ctx != EGL_NO_CONTEXT); -} - -bool QEglContext::isCurrent() const -{ - return current; -} - -EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options) -{ - if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0)) - qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!"); - - EGLConfig* targetConfig = 0; - - static EGLConfig defaultVGConfigs[] = { - QEGL_NO_CONFIG, // 0 Window Renderable Translucent - QEGL_NO_CONFIG, // 1 Window Renderable Opaque - QEGL_NO_CONFIG, // 2 Pixmap Renderable Translucent - QEGL_NO_CONFIG, // 3 Pixmap Renderable Opaque - QEGL_NO_CONFIG, // 4 Pixmap ReadOnly Translucent - QEGL_NO_CONFIG // 5 Pixmap ReadOnly Opaque - }; - if (api == OpenVG) { - if (devType == QInternal::Widget) { - if (options & Translucent) - targetConfig = &(defaultVGConfigs[0]); - else - targetConfig = &(defaultVGConfigs[1]); - } else if (devType == QInternal::Pixmap) { - if (options & Renderable) { - if (options & Translucent) - targetConfig = &(defaultVGConfigs[2]); - else // Opaque - targetConfig = &(defaultVGConfigs[3]); - } else { // Read-only - if (options & Translucent) - targetConfig = &(defaultVGConfigs[4]); - else // Opaque - targetConfig = &(defaultVGConfigs[5]); - } - } - } - - - static EGLConfig defaultGLConfigs[] = { - QEGL_NO_CONFIG, // 0 Window Renderable Translucent - QEGL_NO_CONFIG, // 1 Window Renderable Opaque - QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent - QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque - QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent - QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque - QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent - QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque - }; - if (api == OpenGL) { - if (devType == QInternal::Widget) { - if (options & Translucent) - targetConfig = &(defaultGLConfigs[0]); - else // Opaque - targetConfig = &(defaultGLConfigs[1]); - } else if (devType == QInternal::Pbuffer) { - if (options & Translucent) - targetConfig = &(defaultGLConfigs[2]); - else // Opaque - targetConfig = &(defaultGLConfigs[3]); - } else if (devType == QInternal::Pixmap) { - if (options & Renderable) { - if (options & Translucent) - targetConfig = &(defaultGLConfigs[4]); - else // Opaque - targetConfig = &(defaultGLConfigs[5]); - } else { // ReadOnly - if (options & Translucent) - targetConfig = &(defaultGLConfigs[6]); - else // Opaque - targetConfig = &(defaultGLConfigs[7]); - } - } - } - - if (!targetConfig) { - qWarning("QEgl::defaultConfig() - No default config for device/api/options combo"); - return QEGL_NO_CONFIG; - } - if (*targetConfig != QEGL_NO_CONFIG) - return *targetConfig; - - - // We haven't found an EGL config for the target config yet, so do it now: - - - // Allow overriding from an environment variable: - QByteArray configId; - if (api == OpenVG) - configId = qgetenv("QT_VG_EGL_CONFIG"); - else - configId = qgetenv("QT_GL_EGL_CONFIG"); - if (!configId.isEmpty()) { - // Overridden, so get the EGLConfig for the specified config ID: - EGLint properties[] = { - EGL_CONFIG_ID, (EGLint)configId.toInt(), - EGL_NONE - }; - EGLint configCount = 0; - eglChooseConfig(display(), properties, targetConfig, 1, &configCount); - if (configCount > 0) - return *targetConfig; - qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid"; - } - - QEglProperties configAttribs; - configAttribs.setRenderableType(api); - - EGLint surfaceType; - switch (devType) { - case QInternal::Widget: - surfaceType = EGL_WINDOW_BIT; - break; - case QInternal::Pixmap: - surfaceType = EGL_PIXMAP_BIT; - break; - case QInternal::Pbuffer: - surfaceType = EGL_PBUFFER_BIT; - break; - default: - qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType); - return QEGL_NO_CONFIG; - }; -#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT - // For OpenVG, we try to create a surface using a pre-multiplied format if - // the surface needs to have an alpha channel: - if (api == OpenVG && (options & Translucent)) - surfaceType |= EGL_VG_ALPHA_FORMAT_PRE_BIT; -#endif - configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType); - -#ifdef EGL_BIND_TO_TEXTURE_RGBA - if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) { - if (options & Translucent) - configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); - else - configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); - } -#endif - - // Add paint engine requirements - if (api == OpenVG) { -#if !defined(QVG_SCISSOR_CLIP) && defined(EGL_ALPHA_MASK_SIZE) - configAttribs.setValue(EGL_ALPHA_MASK_SIZE, 1); -#endif - } else { - // Both OpenGL paint engines need to have stencil and sample buffers - configAttribs.setValue(EGL_STENCIL_SIZE, 1); - configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1); -#ifndef QT_OPENGL_ES_2 - // Additionally, the GL1 engine likes to have a depth buffer for clipping - configAttribs.setValue(EGL_DEPTH_SIZE, 1); -#endif - } - - if (options & Translucent) - configAttribs.setValue(EGL_ALPHA_SIZE, 1); - - *targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat); - return *targetConfig; -} - - -// Choose a configuration that matches "properties". -EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match) -{ - QEglProperties props(*properties); - EGLConfig cfg = QEGL_NO_CONFIG; - do { - // Get the number of matching configurations for this set of properties. - EGLint matching = 0; - EGLDisplay dpy = QEgl::display(); - if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching) - continue; - - // If we want the best pixel format, then return the first - // matching configuration. - if (match == QEgl::BestPixelFormat) { - eglChooseConfig(display(), props.properties(), &cfg, 1, &matching); - if (matching < 1) - continue; - return cfg; - } - - // Fetch all of the matching configurations and find the - // first that matches the pixel format we wanted. - EGLint size = matching; - EGLConfig *configs = new EGLConfig [size]; - eglChooseConfig(display(), props.properties(), configs, size, &matching); - for (EGLint index = 0; index < size; ++index) { - EGLint red, green, blue, alpha; - eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red); - eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green); - eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue); - eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha); - if (red == props.value(EGL_RED_SIZE) && - green == props.value(EGL_GREEN_SIZE) && - blue == props.value(EGL_BLUE_SIZE) && - (props.value(EGL_ALPHA_SIZE) == 0 || - alpha == props.value(EGL_ALPHA_SIZE))) { - cfg = configs[index]; - delete [] configs; - return cfg; - } - } - delete [] configs; - } while (props.reduceConfiguration()); - -#ifdef EGL_BIND_TO_TEXTURE_RGBA - // Don't report an error just yet if we failed to get a pbuffer - // configuration with texture rendering. Only report failure if - // we cannot get any pbuffer configurations at all. - if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE && - props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE) -#endif - { - qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration"; - qWarning() << "Requested:" << props.toString(); - qWarning() << "Available:"; - QEgl::dumpAllConfigs(); - } - return QEGL_NO_CONFIG; -} - -bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match) -{ - cfg = QEgl::chooseConfig(&properties, match); - return cfg != QEGL_NO_CONFIG; -} - -EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties) -{ - return QEgl::createSurface(device, cfg, properties); -} - - -// Create the EGLContext. -bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties) -{ - // We need to select the correct API before calling eglCreateContext(). -#ifdef QT_OPENGL_ES -#ifdef EGL_OPENGL_ES_API - if (apiType == QEgl::OpenGL) - eglBindAPI(EGL_OPENGL_ES_API); -#endif -#else -#ifdef EGL_OPENGL_API - if (apiType == QEgl::OpenGL) - eglBindAPI(EGL_OPENGL_API); -#endif -#endif //defined(QT_OPENGL_ES) -#ifdef EGL_OPENVG_API - if (apiType == QEgl::OpenVG) - eglBindAPI(EGL_OPENVG_API); -#endif - - // Create a new context for the configuration. - QEglProperties contextProps; - if (properties) - contextProps = *properties; -#ifdef QT_OPENGL_ES_2 - if (apiType == QEgl::OpenGL) - contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); -#endif - sharing = false; - if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) - shareContext = 0; - if (shareContext) { - ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties()); - if (ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString(); - shareContext = 0; - } else { - sharing = true; - } - } - if (ctx == EGL_NO_CONTEXT) { - ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties()); - if (ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString(); - return false; - } - } - return true; -} - -// Destroy an EGL surface object. If it was current on this context -// then call doneCurrent() for it first. -void QEglContext::destroySurface(EGLSurface surface) -{ - if (surface != EGL_NO_SURFACE) { - if (surface == currentSurface) - doneCurrent(); - eglDestroySurface(display(), surface); - } -} - -// Destroy the context. Note: this does not destroy the surface. -void QEglContext::destroyContext() -{ - if (ctx != EGL_NO_CONTEXT && ownsContext) - eglDestroyContext(display(), ctx); - ctx = EGL_NO_CONTEXT; - cfg = 0; -} - -bool QEglContext::makeCurrent(EGLSurface surface) -{ - if (ctx == EGL_NO_CONTEXT) { - qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current"; - return false; - } - - if (surface == EGL_NO_SURFACE) { - qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current"; - return false; - } - - // If lazyDoneCurrent() was called on the surface, then we may be able - // to assume that it is still current within the thread. - if (surface == currentSurface && currentContext(apiType) == this) { - current = true; - return true; - } - - current = true; - currentSurface = surface; - setCurrentContext(apiType, this); - - // Force the right API to be bound before making the context current. - // The EGL implementation should be able to figure this out from ctx, - // but some systems require the API to be explicitly set anyway. -#ifdef EGL_OPENGL_ES_API - if (apiType == QEgl::OpenGL) - eglBindAPI(EGL_OPENGL_ES_API); -#endif -#ifdef EGL_OPENVG_API - if (apiType == QEgl::OpenVG) - eglBindAPI(EGL_OPENVG_API); -#endif - - bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx); - if (!ok) - qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString(); - return ok; -} - -bool QEglContext::doneCurrent() -{ - // If the context is invalid, we assume that an error was reported - // when makeCurrent() was called. - if (ctx == EGL_NO_CONTEXT) - return false; - - current = false; - currentSurface = EGL_NO_SURFACE; - setCurrentContext(apiType, 0); - - // We need to select the correct API before calling eglMakeCurrent() - // with EGL_NO_CONTEXT because threads can have both OpenGL and OpenVG - // contexts active at the same time. -#ifdef EGL_OPENGL_ES_API - if (apiType == QEgl::OpenGL) - eglBindAPI(EGL_OPENGL_ES_API); -#endif -#ifdef EGL_OPENVG_API - if (apiType == QEgl::OpenVG) - eglBindAPI(EGL_OPENVG_API); -#endif - - bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!ok) - qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString(); - return ok; -} - -// Act as though doneCurrent() was called, but keep the context -// and the surface active for the moment. This allows makeCurrent() -// to skip a call to eglMakeCurrent() if we are using the same -// surface as the last set of painting operations. We leave the -// currentContext() pointer as-is for now. -bool QEglContext::lazyDoneCurrent() -{ - current = false; - return true; -} - -bool QEglContext::swapBuffers(EGLSurface surface) -{ - if(ctx == EGL_NO_CONTEXT) - return false; - - bool ok = eglSwapBuffers(QEgl::display(), surface); - if (!ok) - qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString(); - return ok; -} - -bool QEglContext::swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region) { - QVector<QRect> qrects = region->rects(); - EGLint *gl_rects; - uint count; - uint i; - - count = qrects.size(); - QVarLengthArray <EGLint> arr(4 * count); - gl_rects = arr.data(); - for (i = 0; i < count; i++) { - QRect qrect = qrects[i]; - - gl_rects[4 * i + 0] = qrect.x(); - gl_rects[4 * i + 1] = qrect.y(); - gl_rects[4 * i + 2] = qrect.width(); - gl_rects[4 * i + 3] = qrect.height(); - } - - bool ok = QEgl::eglSwapBuffersRegion2NOK(QEgl::display(), surface, count, gl_rects); - - if (!ok) - qWarning() << "QEglContext::swapBuffersRegion2NOK():" << QEgl::errorString(); - return ok; -} - -int QEglContext::configAttrib(int name) const -{ - EGLint value; - EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value); - if (success) - return value; - else - return EGL_DONT_CARE; -} - -typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*); -typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); - -// Defined in qegl.cpp: -static _eglCreateImageKHR qt_eglCreateImageKHR = 0; -static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0; - -typedef EGLBoolean (EGLAPIENTRY *_eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint*); - -static _eglSwapBuffersRegion2NOK qt_eglSwapBuffersRegion2NOK = 0; - -EGLDisplay QEgl::display() -{ - static EGLDisplay dpy = EGL_NO_DISPLAY; - if (!QEglContextTracker::displayOpened()) { - dpy = eglGetDisplay(nativeDisplay()); - QEglContextTracker::setDisplayOpened(); - if (dpy == EGL_NO_DISPLAY) { - qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY"); - dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); - } - if (dpy == EGL_NO_DISPLAY) { - qWarning("QEgl::display(): Can't even open the default display"); - return EGL_NO_DISPLAY; - } - - if (!eglInitialize(dpy, NULL, NULL)) { - qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString(); - return EGL_NO_DISPLAY; - } - - // Resolve the egl extension function pointers: -#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES) - if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) { - qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); - qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); - } -#endif - - if (QEgl::hasExtension("EGL_NOK_swap_region2")) { - qt_eglSwapBuffersRegion2NOK = (_eglSwapBuffersRegion2NOK) eglGetProcAddress("eglSwapBuffersRegion2NOK"); - } - } - - return dpy; -} - -EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) -{ - if (qt_eglCreateImageKHR) - return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); - - QEgl::display(); // Initialises function pointers - if (qt_eglCreateImageKHR) - return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list); - - qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present"); - return 0; -} - -EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) -{ - if (qt_eglDestroyImageKHR) - return qt_eglDestroyImageKHR(dpy, img); - - QEgl::display(); // Initialises function pointers - if (qt_eglDestroyImageKHR) - return qt_eglDestroyImageKHR(dpy, img); - - qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present"); - return 0; -} - -EGLBoolean QEgl::eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects) -{ - if (qt_eglSwapBuffersRegion2NOK) - return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects); - - QEgl::display(); // Initialises function pointers - if (qt_eglSwapBuffersRegion2NOK) - return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects); - - qWarning("QEgl::eglSwapBuffersRegion2NOK() called but EGL_NOK_swap_region2 extension not present"); - return 0; -} - -EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties) -{ - // Create the native drawable for the paint device. - int devType = device->devType(); - EGLNativePixmapType pixmapDrawable = 0; - EGLNativeWindowType windowDrawable = 0; - bool ok; - if (devType == QInternal::Pixmap) { - pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device)); - ok = (pixmapDrawable != 0); - } else if (devType == QInternal::Widget) { - windowDrawable = nativeWindow(static_cast<QWidget *>(device)); - ok = (windowDrawable != 0); - } else { - ok = false; - } - if (!ok) { - qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable"); - return EGL_NO_SURFACE; - } - - // Create the EGL surface to draw into, based on the native drawable. - const int *props; - if (properties) - props = properties->properties(); - else - props = 0; - EGLSurface surf; - if (devType == QInternal::Widget) - surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props); - else - surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props); - if (surf == EGL_NO_SURFACE) { - qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError()); - } - return surf; -} - - -// Return the error string associated with a specific code. -QString QEgl::errorString(EGLint code) -{ - static const char * const errors[] = { - "Success (0x3000)", // No tr - "Not initialized (0x3001)", // No tr - "Bad access (0x3002)", // No tr - "Bad alloc (0x3003)", // No tr - "Bad attribute (0x3004)", // No tr - "Bad config (0x3005)", // No tr - "Bad context (0x3006)", // No tr - "Bad current surface (0x3007)", // No tr - "Bad display (0x3008)", // No tr - "Bad match (0x3009)", // No tr - "Bad native pixmap (0x300A)", // No tr - "Bad native window (0x300B)", // No tr - "Bad parameter (0x300C)", // No tr - "Bad surface (0x300D)", // No tr - "Context lost (0x300E)" // No tr - }; - if (code >= 0x3000 && code <= 0x300E) { - return QString::fromLatin1(errors[code - 0x3000]); - } else { - return QLatin1String("0x") + QString::number(int(code), 16); - } -} - -// Dump all of the EGL configurations supported by the system. -void QEgl::dumpAllConfigs() -{ - QEglProperties props; - EGLint count = 0; - if (!eglGetConfigs(display(), 0, 0, &count) || count < 1) - return; - EGLConfig *configs = new EGLConfig [count]; - eglGetConfigs(display(), configs, count, &count); - for (EGLint index = 0; index < count; ++index) { - props = QEglProperties(configs[index]); - qWarning() << props.toString(); - } - delete [] configs; -} - -QString QEgl::extensions() -{ - const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS); - return QString(QLatin1String(exts)); -} - -bool QEgl::hasExtension(const char* extensionName) -{ - QList<QByteArray> extensions = - QByteArray(reinterpret_cast<const char *> - (eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' '); - return extensions.contains(extensionName); -} - -QEglContext *QEglContext::currentContext(QEgl::API api) -{ - if (api == QEgl::OpenGL) - return currentGLContext; - else - return currentVGContext; -} - -void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context) -{ - if (api == QEgl::OpenGL) - currentGLContext = context; - else - currentVGContext = context; -} - -QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h deleted file mode 100644 index 3e78b97fcb..0000000000 --- a/src/gui/egl/qegl_p.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QEGL_P_H -#define QEGL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience of -// the QtGui and QtOpenVG modules. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -QT_BEGIN_INCLUDE_NAMESPACE - -#ifndef QT_NO_EGL -#if defined(QT_OPENGL_ES_2) -# include <GLES2/gl2.h> -#endif - -#if defined(QT_GLES_EGL) -# include <GLES/egl.h> -#else -# include <EGL/egl.h> -#endif -#if !defined(EGL_VERSION_1_2) -typedef unsigned int EGLenum; -typedef void *EGLClientBuffer; -#endif -#else - -//types from egltypes.h for compiling stub without EGL headers -typedef int EGLBoolean; -typedef int EGLint; -typedef int EGLenum; -typedef int NativeDisplayType; -typedef void* NativeWindowType; -typedef void* NativePixmapType; -typedef int EGLDisplay; -typedef int EGLConfig; -typedef int EGLSurface; -typedef int EGLContext; -typedef int EGLClientBuffer; -#define EGL_NONE 0x3038 /* Attrib list terminator */ - -#endif - - -// Internally we use the EGL-prefixed native types which are used in EGL >= 1.3. -// For older versions of EGL, we have to define these types ourselves here: -#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED) -#undef EGLNativeWindowType -#undef EGLNativePixmapType -#undef EGLNativeDisplayType -typedef NativeWindowType EGLNativeWindowType; -typedef NativePixmapType EGLNativePixmapType; -typedef NativeDisplayType EGLNativeDisplayType; -#define QEGL_NATIVE_TYPES_DEFINED 1 -#endif - -QT_END_INCLUDE_NAMESPACE - -#include <QtGui/qpaintdevice.h> -#include <QFlags> - -QT_BEGIN_NAMESPACE - -#define QEGL_NO_CONFIG ((EGLConfig)-1) - -#ifndef EGLAPIENTRY -#define EGLAPIENTRY -#endif - -// Declare/define the bits of EGL_KHR_image_base we need: -#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) -typedef void *EGLImageKHR; - -#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) -#define EGL_IMAGE_PRESERVED_KHR 0x30D2 -#define EGL_KHR_image_base -#endif - -#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap) -#define EGL_NATIVE_PIXMAP_KHR 0x30B0 -#define EGL_KHR_image_pixmap -#endif - - -class QEglProperties; - -namespace QEgl { - enum API - { - OpenGL, - OpenVG - }; - - enum PixelFormatMatch - { - ExactPixelFormat, - BestPixelFormat - }; - - enum ConfigOption - { - NoOptions = 0, - Translucent = 0x01, - Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL) - }; - Q_DECLARE_FLAGS(ConfigOptions, ConfigOption) - - // Most of the time we use the same config for things like widgets & pixmaps, so rather than - // go through the eglChooseConfig loop every time, we use defaultConfig, which will return - // the config for a particular device/api/option combo. This function assumes that once a - // config is chosen for a particular combo, it's safe to always use that combo. - Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options); - - Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties* configAttribs, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); - Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs = 0); - - Q_GUI_EXPORT void dumpAllConfigs(); - -#ifdef QT_NO_EGL - Q_GUI_EXPORT QString errorString(EGLint code = 0); -#else - Q_GUI_EXPORT QString errorString(EGLint code = eglGetError()); -#endif - - Q_GUI_EXPORT QString extensions(); - Q_GUI_EXPORT bool hasExtension(const char* extensionName); - - Q_GUI_EXPORT EGLDisplay display(); - - Q_GUI_EXPORT EGLNativeDisplayType nativeDisplay(); - Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget*); - Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap*); - - // Extension functions - Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); - Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img); - Q_GUI_EXPORT EGLBoolean eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects); - -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions) - -QT_END_NAMESPACE - -#endif //QEGL_P_H diff --git a/src/gui/egl/qegl_qpa.cpp b/src/gui/egl/qegl_qpa.cpp deleted file mode 100644 index a0a16a5395..0000000000 --- a/src/gui/egl/qegl_qpa.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtGui/qpaintdevice.h> -#include <QtGui/qpixmap.h> -#include <QtGui/qwidget.h> -#include "qeglcontext_p.h" - -#if !defined(QT_NO_EGL) - -#include <QtGui/private/qapplication_p.h> -#include <QtGui/qdesktopwidget.h> - -QT_BEGIN_NAMESPACE - -EGLNativeDisplayType QEgl::nativeDisplay() -{ - return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); -} - -EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) -{ - return (EGLNativeWindowType)(widget->winId()); -} - -EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap) -{ - Q_UNUSED(pixmap); - return 0; -} - -//EGLDisplay QEglContext::display() -//{ -// return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); -//} - -static QPlatformScreen *screenForDevice(QPaintDevice *device) -{ - QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); - - QList<QPlatformScreen *> screens = pi->screens(); - - int screenNumber; - if (device && device->devType() == QInternal::Widget) - screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); - else - screenNumber = 0; - if (screenNumber < 0 || screenNumber >= screens.size()) - return 0; - return screens[screenNumber]; -} - -// Set pixel format and other properties based on a paint device. -void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) -{ - if (!dev) - return; - - // Find the QOpenGLScreen for this paint device. - QPlatformScreen *screen = screenForDevice(dev); - if (!screen) - return; - int devType = dev->devType(); - if (devType == QInternal::Image) - setPixelFormat(static_cast<QImage *>(dev)->format()); - else - setPixelFormat(screen->format()); -} - -QT_END_NAMESPACE - -#endif // !QT_NO_EGL diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h deleted file mode 100644 index 94654eb2a8..0000000000 --- a/src/gui/egl/qeglcontext_p.h +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QEGLCONTEXT_P_H -#define QEGLCONTEXT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience of -// the QtGui and QtOpenVG modules. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qsize.h> -#include <QtGui/qimage.h> - -#include <QtGui/private/qegl_p.h> -#include <QtGui/private/qeglproperties_p.h> - -QT_BEGIN_NAMESPACE - -class Q_GUI_EXPORT QEglContext -{ -public: - QEglContext(); - ~QEglContext(); - - bool isValid() const; - bool isCurrent() const; - bool isSharing() const { return sharing; } - - QEgl::API api() const { return apiType; } - void setApi(QEgl::API api) { apiType = api; } - - bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat); - bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0); - void destroyContext(); - EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0); - void destroySurface(EGLSurface surface); - - bool makeCurrent(EGLSurface surface); - bool doneCurrent(); - bool lazyDoneCurrent(); - bool swapBuffers(EGLSurface surface); - bool swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region); - - int configAttrib(int name) const; - - EGLContext context() const { return ctx; } - void setContext(EGLContext context) { ctx = context; ownsContext = false;} - - EGLDisplay display() {return QEgl::display();} - - EGLConfig config() const { return cfg; } - void setConfig(EGLConfig config) { cfg = config; } - -private: - QEgl::API apiType; - EGLContext ctx; - EGLConfig cfg; - EGLSurface currentSurface; - bool current; - bool ownsContext; - bool sharing; - - static QEglContext *currentContext(QEgl::API api); - static void setCurrentContext(QEgl::API api, QEglContext *context); - - friend class QMeeGoGraphicsSystem; - friend class QMeeGoPlatformPixmap; -}; - -QT_END_NAMESPACE - -#endif // QEGLCONTEXT_P_H diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp deleted file mode 100644 index 414ad8d06a..0000000000 --- a/src/gui/egl/qeglproperties.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qdebug.h> -#include <QtCore/qstringlist.h> - -#include "qeglproperties_p.h" -#include "qeglcontext_p.h" - -QT_BEGIN_NAMESPACE - -// Initialize a property block. -QEglProperties::QEglProperties() -{ - props.append(EGL_NONE); -} - -QEglProperties::QEglProperties(EGLConfig cfg) -{ - props.append(EGL_NONE); - for (int name = 0x3020; name <= 0x304F; ++name) { - EGLint value; - if (name != EGL_NONE && eglGetConfigAttrib(QEgl::display(), cfg, name, &value)) - setValue(name, value); - } - eglGetError(); // Clear the error state. -} - -// Fetch the current value associated with a property. -int QEglProperties::value(int name) const -{ - for (int index = 0; index < (props.size() - 1); index += 2) { - if (props[index] == name) - return props[index + 1]; - } - - // If the attribute has not been explicitly set, return the EGL default - // The following defaults were taken from the EGL 1.4 spec: - switch(name) { - case EGL_BUFFER_SIZE: return 0; - case EGL_RED_SIZE: return 0; - case EGL_GREEN_SIZE: return 0; - case EGL_BLUE_SIZE: return 0; - case EGL_ALPHA_SIZE: return 0; -#ifdef EGL_LUMINANCE_SIZE - case EGL_LUMINANCE_SIZE: return 0; -#endif -#ifdef EGL_ALPHA_MASK_SIZE - case EGL_ALPHA_MASK_SIZE: return 0; -#endif -#ifdef EGL_BIND_TO_TEXTURE_RGB - case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE; -#endif -#ifdef EGL_BIND_TO_TEXTURE_RGBA - case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE; -#endif -#ifdef EGL_COLOR_BUFFER_TYPE - case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER; -#endif - case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE; - case EGL_CONFIG_ID: return EGL_DONT_CARE; - case EGL_DEPTH_SIZE: return 0; - case EGL_LEVEL: return 0; - case EGL_NATIVE_RENDERABLE: return EGL_DONT_CARE; - case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE; - case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE; - case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE; -#ifdef EGL_RENDERABLE_TYPE - case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT; -#endif - case EGL_SAMPLE_BUFFERS: return 0; - case EGL_SAMPLES: return 0; - case EGL_STENCIL_SIZE: return 0; - case EGL_SURFACE_TYPE: return EGL_WINDOW_BIT; - case EGL_TRANSPARENT_TYPE: return EGL_NONE; - case EGL_TRANSPARENT_RED_VALUE: return EGL_DONT_CARE; - case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE; - case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE; - -#ifdef EGL_VERSION_1_3 - case EGL_CONFORMANT: return 0; - case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE; -#endif - - case EGL_MAX_PBUFFER_HEIGHT: - case EGL_MAX_PBUFFER_WIDTH: - case EGL_MAX_PBUFFER_PIXELS: - case EGL_NATIVE_VISUAL_ID: - case EGL_NONE: - // Attribute does not affect config selection. - return EGL_DONT_CARE; - default: - // Attribute is unknown in EGL <= 1.4. - return EGL_DONT_CARE; - } -} - -// Set the value associated with a property, replacing an existing -// value if there is one. -void QEglProperties::setValue(int name, int value) -{ - for (int index = 0; index < (props.size() - 1); index += 2) { - if (props[index] == name) { - props[index + 1] = value; - return; - } - } - props[props.size() - 1] = name; - props.append(value); - props.append(EGL_NONE); -} - -// Remove a property value. Returns false if the property is not present. -bool QEglProperties::removeValue(int name) -{ - for (int index = 0; index < (props.size() - 1); index += 2) { - if (props[index] == name) { - while ((index + 2) < props.size()) { - props[index] = props[index + 2]; - ++index; - } - props.resize(props.size() - 2); - return true; - } - } - return false; -} - -void QEglProperties::setDeviceType(int devType) -{ - if (devType == QInternal::Pixmap || devType == QInternal::Image) - setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT); - else if (devType == QInternal::Pbuffer) - setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT); - else - setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); -} - - -// Sets the red, green, blue, and alpha sizes based on a pixel format. -// Normally used to match a configuration request to the screen format. -void QEglProperties::setPixelFormat(QImage::Format pixelFormat) -{ - int red, green, blue, alpha; - switch (pixelFormat) { - case QImage::Format_RGB32: - case QImage::Format_RGB888: - red = green = blue = 8; alpha = 0; break; - case QImage::Format_ARGB32: - case QImage::Format_ARGB32_Premultiplied: - red = green = blue = alpha = 8; break; - case QImage::Format_RGB16: - red = 5; green = 6; blue = 5; alpha = 0; break; - case QImage::Format_ARGB8565_Premultiplied: - red = 5; green = 6; blue = 5; alpha = 8; break; - case QImage::Format_RGB666: - red = green = blue = 6; alpha = 0; break; - case QImage::Format_ARGB6666_Premultiplied: - red = green = blue = alpha = 6; break; - case QImage::Format_RGB555: - red = green = blue = 5; alpha = 0; break; - case QImage::Format_ARGB8555_Premultiplied: - red = green = blue = 5; alpha = 8; break; - case QImage::Format_RGB444: - red = green = blue = 4; alpha = 0; break; - case QImage::Format_ARGB4444_Premultiplied: - red = green = blue = alpha = 4; break; - default: - qWarning() << "QEglProperties::setPixelFormat(): Unsupported pixel format"; - red = green = blue = alpha = 1; break; - } - setValue(EGL_RED_SIZE, red); - setValue(EGL_GREEN_SIZE, green); - setValue(EGL_BLUE_SIZE, blue); - setValue(EGL_ALPHA_SIZE, alpha); -} - -void QEglProperties::setRenderableType(QEgl::API api) -{ -#ifdef EGL_RENDERABLE_TYPE -#if defined(QT_OPENGL_ES_2) - if (api == QEgl::OpenGL) - setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); -#elif defined(QT_OPENGL_ES) - if (api == QEgl::OpenGL) - setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); -#elif defined(EGL_OPENGL_BIT) - if (api == QEgl::OpenGL) - setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT); -#endif -#ifdef EGL_OPENVG_BIT - if (api == QEgl::OpenVG) - setValue(EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT); -#endif -#else - Q_UNUSED(api); -#endif -} - -// Reduce the complexity of a configuration request to ask for less -// because the previous request did not result in success. Returns -// true if the complexity was reduced, or false if no further -// reductions in complexity are possible. -bool QEglProperties::reduceConfiguration() -{ -#ifdef EGL_SWAP_BEHAVIOR - if (value(EGL_SWAP_BEHAVIOR) != EGL_DONT_CARE) - removeValue(EGL_SWAP_BEHAVIOR); -#endif - -#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT - // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't - // find a config which supports pre-multiplied formats, remove the flag on the surface type: - EGLint surfaceType = value(EGL_SURFACE_TYPE); - if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) { - surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT; - setValue(EGL_SURFACE_TYPE, surfaceType); - return true; - } -#endif - // EGL chooses configs with the highest color depth over - // those with smaller (but faster) lower color depths. One - // way around this is to set EGL_BUFFER_SIZE to 16, which - // trumps the others. Of course, there may not be a 16-bit - // config available, so it's the first restraint we remove. - if (value(EGL_BUFFER_SIZE) == 16) { - removeValue(EGL_BUFFER_SIZE); - return true; - } - if (removeValue(EGL_SAMPLE_BUFFERS)) { - removeValue(EGL_SAMPLES); - return true; - } - if (removeValue(EGL_ALPHA_SIZE)) { -#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB) - if (removeValue(EGL_BIND_TO_TEXTURE_RGBA)) - setValue(EGL_BIND_TO_TEXTURE_RGB, TRUE); -#endif - return true; - } - if (removeValue(EGL_STENCIL_SIZE)) - return true; - if (removeValue(EGL_DEPTH_SIZE)) - return true; -#ifdef EGL_BIND_TO_TEXTURE_RGB - if (removeValue(EGL_BIND_TO_TEXTURE_RGB)) - return true; -#endif - return false; -} - -static void addTag(QString& str, const QString& tag) -{ - int lastnl = str.lastIndexOf(QLatin1String("\n")); - if (lastnl == -1) - lastnl = 0; - if ((str.length() - lastnl) >= 50) - str += QLatin1String("\n "); - str += tag; -} - -// Convert a property list to a string suitable for debug output. -QString QEglProperties::toString() const -{ - QString str; - int val; - - val = value(EGL_CONFIG_ID); - if (val != EGL_DONT_CARE) { - str += QLatin1String("id="); - str += QString::number(val); - str += QLatin1Char(' '); - } - -#ifdef EGL_RENDERABLE_TYPE - val = value(EGL_RENDERABLE_TYPE); - if (val != EGL_DONT_CARE) { - str += QLatin1String("type="); - QStringList types; - if ((val & EGL_OPENGL_ES_BIT) != 0) - types += QLatin1String("es1"); -#ifdef EGL_OPENGL_ES2_BIT - if ((val & EGL_OPENGL_ES2_BIT) != 0) - types += QLatin1String("es2"); -#endif -#ifdef EGL_OPENGL_BIT - if ((val & EGL_OPENGL_BIT) != 0) - types += QLatin1String("gl"); -#endif - if ((val & EGL_OPENVG_BIT) != 0) - types += QLatin1String("vg"); - if ((val & ~7) != 0) - types += QString::number(val); - str += types.join(QLatin1String(",")); - } else { - str += QLatin1String("type=any"); - } -#else - str += QLatin1String("type=es1"); -#endif - - int red = value(EGL_RED_SIZE); - int green = value(EGL_GREEN_SIZE); - int blue = value(EGL_BLUE_SIZE); - int alpha = value(EGL_ALPHA_SIZE); - int bufferSize = value(EGL_BUFFER_SIZE); - if (bufferSize == (red + green + blue + alpha)) - bufferSize = 0; - str += QLatin1String(" rgba="); - str += QString::number(red); - str += QLatin1Char(','); - str += QString::number(green); - str += QLatin1Char(','); - str += QString::number(blue); - str += QLatin1Char(','); - str += QString::number(alpha); - if (bufferSize != 0) { - // Only report buffer size if different than r+g+b+a. - str += QLatin1String(" buffer-size="); - str += QString::number(bufferSize); - } - -#ifdef EGL_COLOR_BUFFER_TYPE - val = value(EGL_COLOR_BUFFER_TYPE); - if (val == EGL_LUMINANCE_BUFFER) { - addTag(str, QLatin1String(" color-buffer-type=luminance")); - } else if (val != EGL_DONT_CARE && val != EGL_RGB_BUFFER) { - addTag(str, QLatin1String(" color-buffer-type=")); - str += QString::number(val, 16); - } -#endif - - val = value(EGL_DEPTH_SIZE); - if (val != 0) { - addTag(str, QLatin1String(" depth=")); - str += QString::number(val); - } - - val = value(EGL_STENCIL_SIZE); - if (val != 0) { - addTag(str, QLatin1String(" stencil=")); - str += QString::number(val); - } - - val = value(EGL_SURFACE_TYPE); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" surface-type=")); - QStringList types; - if ((val & EGL_WINDOW_BIT) != 0) - types += QLatin1String("window"); - if ((val & EGL_PIXMAP_BIT) != 0) - types += QLatin1String("pixmap"); - if ((val & EGL_PBUFFER_BIT) != 0) - types += QLatin1String("pbuffer"); -#ifdef EGL_VG_COLORSPACE_LINEAR_BIT - if ((val & EGL_VG_COLORSPACE_LINEAR_BIT) != 0) - types += QLatin1String("vg-colorspace-linear"); -#endif -#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT - if ((val & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0) - types += QLatin1String("vg-alpha-format-pre"); -#endif - if ((val & ~(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT -#ifdef EGL_VG_COLORSPACE_LINEAR_BIT - | EGL_VG_COLORSPACE_LINEAR_BIT -#endif -#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT - | EGL_VG_ALPHA_FORMAT_PRE_BIT -#endif - )) != 0) { - types += QString::number(val); - } - str += types.join(QLatin1String(",")); - } - - val = value(EGL_CONFIG_CAVEAT); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" caveat=")); - if (val == EGL_NONE) - str += QLatin1String("none"); - else if (val == EGL_SLOW_CONFIG) - str += QLatin1String("slow"); - else if (val == EGL_NON_CONFORMANT_CONFIG) - str += QLatin1String("non-conformant"); - else - str += QString::number(val, 16); - } - - val = value(EGL_LEVEL); - if (val != 0) { - addTag(str, QLatin1String(" level=")); - str += QString::number(val); - } - - int width, height, pixels; - width = value(EGL_MAX_PBUFFER_WIDTH); - height = value(EGL_MAX_PBUFFER_HEIGHT); - pixels = value(EGL_MAX_PBUFFER_PIXELS); - if (height != EGL_DONT_CARE || width != EGL_DONT_CARE) { - addTag(str, QLatin1String(" max-pbuffer-size=")); - str += QString::number(width); - str += QLatin1Char('x'); - str += QString::number(height); - if (pixels != (width * height)) { - addTag(str, QLatin1String(" max-pbuffer-pixels=")); - str += QString::number(pixels); - } - } - - val = value(EGL_NATIVE_RENDERABLE); - if (val != EGL_DONT_CARE) { - if (val) - addTag(str, QLatin1String(" native-renderable=true")); - else - addTag(str, QLatin1String(" native-renderable=false")); - } - - val = value(EGL_NATIVE_VISUAL_ID); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" visual-id=")); - str += QString::number(val); - } - - val = value(EGL_NATIVE_VISUAL_TYPE); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" visual-type=")); - str += QString::number(val); - } - -#ifdef EGL_PRESERVED_RESOURCES - val = value(EGL_PRESERVED_RESOURCES); - if (val != EGL_DONT_CARE) { - if (val) - addTag(str, QLatin1String(" preserved-resources=true")); - else - addTag(str, QLatin1String(" preserved-resources=false")); - } -#endif - - val = value(EGL_SAMPLES); - if (val != 0) { - addTag(str, QLatin1String(" samples=")); - str += QString::number(val); - } - - val = value(EGL_SAMPLE_BUFFERS); - if (val != 0) { - addTag(str, QLatin1String(" sample-buffers=")); - str += QString::number(val); - } - - val = value(EGL_TRANSPARENT_TYPE); - if (val == EGL_TRANSPARENT_RGB) { - addTag(str, QLatin1String(" transparent-rgb=")); - str += QString::number(value(EGL_TRANSPARENT_RED_VALUE)); - str += QLatin1Char(','); - str += QString::number(value(EGL_TRANSPARENT_GREEN_VALUE)); - str += QLatin1Char(','); - str += QString::number(value(EGL_TRANSPARENT_BLUE_VALUE)); - } - -#if defined(EGL_BIND_TO_TEXTURE_RGB) && defined(EGL_BIND_TO_TEXTURE_RGBA) - val = value(EGL_BIND_TO_TEXTURE_RGB); - int val2 = value(EGL_BIND_TO_TEXTURE_RGBA); - if (val != EGL_DONT_CARE || val2 != EGL_DONT_CARE) { - addTag(str, QLatin1String(" bind-texture=")); - if (val == EGL_TRUE) - str += QLatin1String("rgb"); - else - str += QLatin1String("no-rgb"); - if (val2 == EGL_TRUE) - str += QLatin1String(",rgba"); - else - str += QLatin1String(",no-rgba"); - } -#endif - -#ifdef EGL_MIN_SWAP_INTERVAL - val = value(EGL_MIN_SWAP_INTERVAL); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" min-swap-interval=")); - str += QString::number(val); - } -#endif - -#ifdef EGL_MIN_SWAP_INTERVAL - val = value(EGL_MAX_SWAP_INTERVAL); - if (val != EGL_DONT_CARE) { - addTag(str, QLatin1String(" max-swap-interval=")); - str += QString::number(val); - } -#endif - -#ifdef EGL_LUMINANCE_SIZE - val = value(EGL_LUMINANCE_SIZE); - if (val != 0) { - addTag(str, QLatin1String(" luminance=")); - str += QString::number(val); - } -#endif - -#ifdef EGL_ALPHA_MASK_SIZE - val = value(EGL_ALPHA_MASK_SIZE); - if (val != 0) { - addTag(str, QLatin1String(" alpha-mask=")); - str += QString::number(val); - } -#endif - -#ifdef EGL_CONFORMANT - val = value(EGL_CONFORMANT); - if (val != 0) { - if (val) - addTag(str, QLatin1String(" conformant=true")); - else - addTag(str, QLatin1String(" conformant=false")); - } -#endif - - return str; -} - -QT_END_NAMESPACE - - diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h deleted file mode 100644 index a5fc8f9b1f..0000000000 --- a/src/gui/egl/qeglproperties_p.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QEGLPROPERTIES_P_H -#define QEGLPROPERTIES_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the QtGui and QtOpenVG modules. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qvarlengtharray.h> -#include <QtGui/qimage.h> - -#include <QtGui/private/qegl_p.h> - -QT_BEGIN_NAMESPACE - -class QPaintDevice; - -class Q_GUI_EXPORT QEglProperties -{ -public: - QEglProperties(); - QEglProperties(EGLConfig); - QEglProperties(const QEglProperties& other) : props(other.props) {} - ~QEglProperties() {} - - int value(int name) const; - void setValue(int name, int value); - bool removeValue(int name); - bool isEmpty() const { return props[0] == EGL_NONE; } - - const int *properties() const { return props.constData(); } - - void setPixelFormat(QImage::Format pixelFormat); - void setDeviceType(int devType); - void setPaintDeviceFormat(QPaintDevice *dev); - void setRenderableType(QEgl::API api); - - bool reduceConfiguration(); - - QString toString() const; - -private: - QVarLengthArray<int> props; -}; - -QT_END_NAMESPACE - -#endif // QEGLPROPERTIES_P_H diff --git a/src/gui/gui.pro b/src/gui/gui.pro index db045930a3..2cee31fce1 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -32,8 +32,6 @@ include(util/util.pri) include(math3d/math3d.pri) include(opengl/opengl.pri) -include(egl/egl.pri) - QMAKE_LIBS += $$QMAKE_LIBS_GUI DEFINES += Q_INTERNAL_QAPP_SRC @@ -59,20 +57,10 @@ win32:!contains(QT_CONFIG, directwrite) { DEFINES += QT_NO_DIRECTWRITE } -contains(QMAKE_MAC_XARCH, no) { - DEFINES += QT_NO_MAC_XARCH -} else { win32-g++*|!win32:!win32-icc*:!macx-icc* { mmx { mmx_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: mmx_compiler.commands += -Xarch_i386 -mmmx - x86_64: mmx_compiler.commands += -Xarch_x86_64 -mmmx - } else { - mmx_compiler.commands += -mmmx - } - + mmx_compiler.commands += -mmmx mmx_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} mmx_compiler.dependency_type = TYPE_C mmx_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -84,14 +72,7 @@ contains(QMAKE_MAC_XARCH, no) { } 3dnow { mmx3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: mmx3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -mmmx - x86_64: mmx3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -mmmx - } else { - mmx3dnow_compiler.commands += -m3dnow -mmmx - } - + mmx3dnow_compiler.commands += -m3dnow -mmmx mmx3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} mmx3dnow_compiler.dependency_type = TYPE_C mmx3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -102,14 +83,7 @@ contains(QMAKE_MAC_XARCH, no) { QMAKE_EXTRA_COMPILERS += mmx3dnow_compiler sse { sse3dnow_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: sse3dnow_compiler.commands += -Xarch_i386 -m3dnow -Xarch_i386 -msse - x86_64: sse3dnow_compiler.commands += -Xarch_x86_64 -m3dnow -Xarch_x86_64 -msse - } else { - sse3dnow_compiler.commands += -m3dnow -msse - } - + sse3dnow_compiler.commands += -m3dnow -msse sse3dnow_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} sse3dnow_compiler.dependency_type = TYPE_C sse3dnow_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -122,14 +96,7 @@ contains(QMAKE_MAC_XARCH, no) { } sse { sse_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: sse_compiler.commands += -Xarch_i386 -msse - x86_64: sse_compiler.commands += -Xarch_x86_64 -msse - } else { - sse_compiler.commands += -msse - } - + sse_compiler.commands += -msse sse_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} sse_compiler.dependency_type = TYPE_C sse_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -141,14 +108,7 @@ contains(QMAKE_MAC_XARCH, no) { } sse2 { sse2_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: sse2_compiler.commands += -Xarch_i386 -msse2 - x86_64: sse2_compiler.commands += -Xarch_x86_64 -msse2 - } else { - sse2_compiler.commands += -msse2 - } - + sse2_compiler.commands += -msse2 sse2_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} sse2_compiler.dependency_type = TYPE_C sse2_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -160,14 +120,7 @@ contains(QMAKE_MAC_XARCH, no) { } ssse3 { ssse3_compiler.commands = $$QMAKE_CXX -c -Winline - - mac { - x86: ssse3_compiler.commands += -Xarch_i386 -mssse3 - x86_64: ssse3_compiler.commands += -Xarch_x86_64 -mssse3 - } else { - ssse3_compiler.commands += -mssse3 - } - + ssse3_compiler.commands += -mssse3 ssse3_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} ssse3_compiler.dependency_type = TYPE_C ssse3_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} @@ -198,4 +151,3 @@ contains(QMAKE_MAC_XARCH, no) { ssse3: SOURCES += $$SSSE3_SOURCES iwmmxt: SOURCES += $$IWMMXT_SOURCES } -} diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 3e53b04728..61a3895a6b 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -50,6 +50,7 @@ #include "qstringlist.h" #include "qvariant.h" #include "qimagepixmapcleanuphooks_p.h" +#include "qplatformintegration_qpa.h" #include <ctype.h> #include <stdlib.h> #include <limits.h> @@ -62,6 +63,7 @@ #include <qhash.h> +#include <private/qguiapplication_p.h> #include <private/qpaintengine_raster_p.h> #include <private/qimage_p.h> @@ -4900,7 +4902,9 @@ QPaintEngine *QImage::paintEngine() const return 0; if (!d->paintEngine) { - d->paintEngine = new QRasterPaintEngine(const_cast<QImage *>(this)); + QPaintDevice *paintDevice = const_cast<QImage *>(this); + QPaintEngine *paintEngine = QGuiApplicationPrivate::platformIntegration()->createImagePaintEngine(paintDevice); + d->paintEngine = paintEngine ? paintEngine : new QRasterPaintEngine(paintDevice); } return d->paintEngine; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 42ce3745de..26690c78cf 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -696,6 +696,8 @@ void QGuiApplicationPrivate::init() // trigger registering of QVariant's GUI types qRegisterGuiVariant(); + QWindowSystemInterfacePrivate::eventTime.start(); + is_app_running = true; init_plugins(pluginList); QWindowSystemInterface::sendWindowSystemEvents(QCoreApplicationPrivate::eventDispatcher, QEventLoop::AllEvents); @@ -753,7 +755,17 @@ static QClipboard *clipboard(); #endif /*! - Returns the currently held keyboard modifiers. + Returns the current state of the modifier keys on the keyboard. The current + state is updated sychronously as the event queue is emptied of events that + will spontaneously change the keyboard state (QEvent::KeyPress and + QEvent::KeyRelease events). + + It should be noted this may not reflect the actual keys held on the input + device at the time of calling but rather the modifiers as last reported in + one of the above events. If no keys are being held Qt::NoModifier is + returned. + + \sa mouseButtons(), queryKeyboardModifiers() */ Qt::KeyboardModifiers QGuiApplication::keyboardModifiers() { @@ -761,7 +773,39 @@ Qt::KeyboardModifiers QGuiApplication::keyboardModifiers() } /*! - Returns the currently held mouse buttons. + \fn Qt::KeyboardModifiers QApplication::queryKeyboardModifiers() + + Queries and returns the state of the modifier keys on the keyboard. + Unlike keyboardModifiers, this method returns the actual keys held + on the input device at the time of calling the method. + + It does not rely on the keypress events having been received by this + process, which makes it possible to check the modifiers while moving + a window, for instance. Note that in most cases, you should use + keyboardModifiers(), which is faster and more accurate since it contains + the state of the modifiers as they were when the currently processed + event was received. + + \sa keyboardModifiers() +*/ +Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers() +{ + QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); + return pi->queryKeyboardModifiers(); +} + +/*! + Returns the current state of the buttons on the mouse. The current state is + updated syncronously as the event queue is emptied of events that will + spontaneously change the mouse state (QEvent::MouseButtonPress and + QEvent::MouseButtonRelease events). + + It should be noted this may not reflect the actual buttons held on the + input device at the time of calling but rather the mouse buttons as last + reported in one of the above events. If no mouse buttons are being held + Qt::NoButton is returned. + + \sa keyboardModifiers() */ Qt::MouseButtons QGuiApplication::mouseButtons() { diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index c374a05986..6fdbb000fe 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -113,6 +113,7 @@ public: static void setPalette(const QPalette &pal); static Qt::KeyboardModifiers keyboardModifiers(); + static Qt::KeyboardModifiers queryKeyboardModifiers(); static Qt::MouseButtons mouseButtons(); static void setLayoutDirection(Qt::LayoutDirection direction); diff --git a/src/gui/kernel/qplatformdrag_qpa.cpp b/src/gui/kernel/qplatformdrag_qpa.cpp index 832b91db7e..0e7b0f41cc 100644 --- a/src/gui/kernel/qplatformdrag_qpa.cpp +++ b/src/gui/kernel/qplatformdrag_qpa.cpp @@ -88,6 +88,7 @@ QPlatformDrag::QPlatformDrag() : d_ptr(new QPlatformDragPrivate) QPlatformDrag::~QPlatformDrag() { + delete d_ptr; } QDrag *QPlatformDrag::currentDrag() const diff --git a/src/gui/kernel/qplatformdrag_qpa.h b/src/gui/kernel/qplatformdrag_qpa.h index 7d22c69947..22133706d1 100644 --- a/src/gui/kernel/qplatformdrag_qpa.h +++ b/src/gui/kernel/qplatformdrag_qpa.h @@ -100,6 +100,8 @@ public: private: QPlatformDragPrivate *d_ptr; + + Q_DISABLE_COPY(QPlatformDrag) }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp index 7a3fe05f7a..e8721edce7 100644 --- a/src/gui/kernel/qplatformintegration_qpa.cpp +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -241,6 +241,15 @@ QPlatformSharedGraphicsCache *QPlatformIntegration::createPlatformSharedGraphics } /*! + Factory function for QPaintEngine. This function will return 0 if the platform + integration does not support creating any paint engine the given \a paintDevice. +*/ +QPaintEngine *QPlatformIntegration::createImagePaintEngine(QPaintDevice *paintDevice) const +{ + return 0; +} + +/*! Returns the platforms input context. The default implementation returns 0, implying no input method support. @@ -282,6 +291,11 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const return 0; } +Qt::KeyboardModifiers QPlatformIntegration::queryKeyboardModifiers() const +{ + return QGuiApplication::keyboardModifiers(); +} + /*! Should be called by the implementation whenever a new screen is added. diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h index 483964b8f3..3f9de9df5e 100644 --- a/src/gui/kernel/qplatformintegration_qpa.h +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -91,6 +91,7 @@ public: virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; #endif virtual QPlatformSharedGraphicsCache *createPlatformSharedGraphicsCache(const char *cacheId) const; + virtual QPaintEngine *createImagePaintEngine(QPaintDevice *paintDevice) const; // Event dispatcher: virtual QAbstractEventDispatcher *guiThreadEventDispatcher() const = 0; @@ -123,6 +124,8 @@ public: virtual QVariant styleHint(StyleHint hint) const; + virtual Qt::KeyboardModifiers queryKeyboardModifiers() const; + virtual QPlatformTheme *platformTheme() const; protected: diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 04c2617838..367cee70e3 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1386,7 +1386,7 @@ void QWindow::hideEvent(QHideEvent *ev) /*! Override this to handle any event sent to the window. - Remembet to call the base class version if you wish for mouse events, + Remember to call the base class version if you wish for mouse events, key events, resize events, etc to be dispatched as usual. */ bool QWindow::event(QEvent *ev) diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 5b77d97950..be9ac8e545 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -QTime QWindowSystemInterfacePrivate::eventTime; +QElapsedTimer QWindowSystemInterfacePrivate::eventTime; //------------------------------------------------------------ // diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index f5c141b4c9..fe97b486ad 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -42,6 +42,7 @@ #define QWINDOWSYSTEMINTERFACE_QPA_P_H #include "qwindowsysteminterface_qpa.h" +#include <QElapsedTimer> QT_BEGIN_HEADER @@ -272,7 +273,7 @@ public: static WindowSystemEvent * getWindowSystemEvent(); static void queueWindowSystemEvent(WindowSystemEvent *ev); - static QTime eventTime; + static QElapsedTimer eventTime; static QList<QTouchEvent::TouchPoint> convertTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, QEvent::Type *type); }; diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp index eb32ac162f..73be87bc1d 100644 --- a/src/gui/opengl/qopenglpaintengine.cpp +++ b/src/gui/opengl/qopenglpaintengine.cpp @@ -1405,8 +1405,7 @@ void QOpenGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) // don't try to cache huge fonts or vastly transformed fonts QFontEngine *fontEngine = textItem->fontEngine(); - const qreal pixelSize = fontEngine->fontDef.pixelSize; - if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) { + if (shouldDrawCachedGlyphs(fontEngine, s->matrix) || det < 0.25f || det > 4.f) { QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(textItem->fontEngine()->glyphFormat) : d->glyphCacheType; @@ -1460,8 +1459,7 @@ void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &text bool drawCached = txtype < QTransform::TxProject; // don't try to cache huge fonts or vastly transformed fonts - const qreal pixelSize = ti.fontEngine->fontDef.pixelSize; - if (shouldDrawCachedGlyphs(pixelSize, s->matrix) || det < 0.25f || det > 4.f) + if (shouldDrawCachedGlyphs(ti.fontEngine, s->matrix) || det < 0.25f || det > 4.f) drawCached = false; QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0 diff --git a/src/gui/opengl/qopenglpaintengine_p.h b/src/gui/opengl/qopenglpaintengine_p.h index 0a6ef2a4d2..1b3dfbae28 100644 --- a/src/gui/opengl/qopenglpaintengine_p.h +++ b/src/gui/opengl/qopenglpaintengine_p.h @@ -157,7 +157,7 @@ public: void setRenderTextActive(bool); bool isNativePaintingActive() const; - bool supportsTransformations(qreal, const QTransform &) const { return true; } + bool supportsTransformations(QFontEngine *, const QTransform &) const { return true; } private: Q_DISABLE_COPY(QOpenGL2PaintEngineEx) diff --git a/src/gui/opengl/qopengltextureglyphcache_p.h b/src/gui/opengl/qopengltextureglyphcache_p.h index 1b4f4f7429..4b6101e7c9 100644 --- a/src/gui/opengl/qopengltextureglyphcache_p.h +++ b/src/gui/opengl/qopengltextureglyphcache_p.h @@ -72,7 +72,7 @@ public: , m_width(0) , m_height(0) { - if (ctx && !ctx->d_func()->workaround_brokenFBOReadBack) + if (!ctx->d_func()->workaround_brokenFBOReadBack) QOpenGLFunctions(ctx).glGenFramebuffers(1, &m_fbo); #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index f2aac442dc..b5e8bca7e0 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2467,6 +2467,15 @@ static inline bool monoVal(const uchar* s, int x) /*! \internal + */ +QRasterBuffer *QRasterPaintEngine::rasterBuffer() +{ + Q_D(QRasterPaintEngine); + return d->rasterBuffer.data(); +} + +/*! + \internal */ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h) { @@ -2923,7 +2932,7 @@ void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) ensureRasterState(); QFontEngine *fontEngine = textItem->fontEngine(); - if (shouldDrawCachedGlyphs(fontEngine->fontDef.pixelSize, state()->matrix)) { + if (shouldDrawCachedGlyphs(fontEngine, state()->matrix)) { drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions, fontEngine); } else if (state()->matrix.type() < QTransform::TxProject) { @@ -3207,18 +3216,18 @@ void QRasterPaintEngine::releaseDC(HDC) const #endif -bool QRasterPaintEngine::supportsTransformations(const QFontEngine *fontEngine) const +bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine) const { const QTransform &m = state()->matrix; - return supportsTransformations(fontEngine->fontDef.pixelSize, m); + return supportsTransformations(fontEngine, m); } -bool QRasterPaintEngine::supportsTransformations(qreal pixelSize, const QTransform &m) const +bool QRasterPaintEngine::supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const { if (m.type() >= QTransform::TxProject) return true; - return !shouldDrawCachedGlyphs(pixelSize, m); + return !shouldDrawCachedGlyphs(fontEngine, m); } /*! diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 7b353188a3..79ed03e393 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -194,8 +194,11 @@ public: void clip(const QVectorPath &path, Qt::ClipOperation op); void clip(const QRect &rect, Qt::ClipOperation op); void clip(const QRegion ®ion, Qt::ClipOperation op); + inline const QClipData *clip() const; void drawStaticTextItem(QStaticTextItem *textItem); + virtual bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, + QFontEngine *fontEngine); enum ClipType { RectClip, @@ -227,14 +230,15 @@ public: static bool clearTypeFontsEnabled(); #endif + QRasterBuffer *rasterBuffer(); void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h); Type type() const { return Raster; } QPoint coordinateOffset() const; - bool supportsTransformations(const QFontEngine *fontEngine) const; - bool supportsTransformations(qreal pixelSize, const QTransform &m) const; + bool supportsTransformations(QFontEngine *fontEngine) const; + bool supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const; protected: QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *); @@ -247,10 +251,6 @@ private: void fillRect(const QRectF &rect, QSpanData *data); void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill); - bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, - QFontEngine *fontEngine); - - bool setClipRectInDeviceCoords(const QRect &r, Qt::ClipOperation op); inline void ensureBrush(const QBrush &brush) { @@ -492,6 +492,12 @@ inline const QClipData *QRasterPaintEnginePrivate::clip() const { return baseClip.data(); } +inline const QClipData *QRasterPaintEngine::clip() const { + Q_D(const QRasterPaintEngine); + if (state() && state()->clip && state()->clip->enabled) + return state()->clip; + return d->baseClip.data(); +} QT_END_NAMESPACE #endif // QPAINTENGINE_RASTER_P_H diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 93f36ba0ab..36414f4774 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -1081,9 +1081,9 @@ void QPaintEngineEx::drawStaticTextItem(QStaticTextItem *staticTextItem) } } -bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform &m) const +bool QPaintEngineEx::supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const { - Q_UNUSED(pixelSize); + Q_UNUSED(fontEngine); if (!m.isAffine()) return true; @@ -1091,8 +1091,9 @@ bool QPaintEngineEx::supportsTransformations(qreal pixelSize, const QTransform & return false; } -bool QPaintEngineEx::shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const +bool QPaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const { + qreal pixelSize = fontEngine->fontDef.pixelSize; return (pixelSize * pixelSize * qAbs(m.determinant())) < QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE; } diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index 62c5d972de..bc944b2297 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -226,8 +226,8 @@ public: IsEmulationEngine = 0x02 // If set, this object is a QEmulationEngine. }; virtual uint flags() const {return 0;} - virtual bool supportsTransformations(qreal pixelSize, const QTransform &m) const; - virtual bool shouldDrawCachedGlyphs(qreal pixelSize, const QTransform &m) const; + virtual bool supportsTransformations(QFontEngine *fontEngine, const QTransform &m) const; + virtual bool shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const; protected: QPaintEngineEx(QPaintEngineExPrivate &data); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 0f5468df4e..eafbe87b31 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -90,7 +90,7 @@ void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, int tabstops, int* tabarray, int tabarraylen, QPainter *painter); -static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine, QTextCharFormat::UnderlineStyle underlineStyle, QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); @@ -5551,14 +5551,9 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) QVarLengthArray<QFixedPoint, 128> fixedPointPositions(count); QRawFontPrivate *fontD = QRawFontPrivate::get(font); - bool supportsTransformations; - if (d->extended != 0) { - supportsTransformations = d->extended->supportsTransformations(fontD->fontEngine->fontDef.pixelSize, - d->state->matrix); - } else { - supportsTransformations = d->engine->type() == QPaintEngine::CoreGraphics - || d->state->matrix.isAffine(); - } + bool supportsTransformations = d->extended + ? d->extended->supportsTransformations(fontD->fontEngine, d->state->matrix) + : d->engine->type() == QPaintEngine::CoreGraphics || d->state->matrix.isAffine(); for (int i=0; i<count; ++i) { QPointF processedPosition = position + glyphPositions[i]; @@ -5646,6 +5641,7 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), fontEngine, + 0, // textEngine (underline ? QTextCharFormat::SingleUnderline : QTextCharFormat::NoUnderline), @@ -5739,7 +5735,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText return; } - bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.pixelSize(), + bool supportsTransformations = d->extended->supportsTransformations(staticText_d->font.d->engineForScript(QUnicodeTables::Common), d->state->matrix); if (supportsTransformations && !staticText_d->untransformedCoordinates) { staticText_d->untransformedCoordinates = true; @@ -6182,7 +6178,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) return pixmap; } -static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, QTextEngine *textEngine, QTextCharFormat::UnderlineStyle underlineStyle, QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat) @@ -6227,15 +6223,17 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); painter->restore(); } else if (underlineStyle != QTextCharFormat::NoUnderline) { - QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos); - QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); pen.setStyle((Qt::PenStyle)(underlineStyle)); painter->setPen(pen); - painter->drawLine(underLine); + QLineF underline(line.x1(), underlinePos, line.x2(), underlinePos); + if (textEngine) + textEngine->addUnderline(painter, underline); + else + painter->drawLine(underline); } pen.setStyle(Qt::SolidLine); @@ -6245,14 +6243,20 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QLineF strikeOutLine = line; strikeOutLine.translate(0., - fe->ascent().toReal() / 3.); painter->setPen(pen); - painter->drawLine(strikeOutLine); + if (textEngine) + textEngine->addStrikeOut(painter, strikeOutLine); + else + painter->drawLine(strikeOutLine); } if (flags & QTextItem::Overline) { - QLineF overLine = line; - overLine.translate(0., - fe->ascent().toReal()); + QLineF overline = line; + overline.translate(0., - fe->ascent().toReal()); painter->setPen(pen); - painter->drawLine(overLine); + if (textEngine) + textEngine->addOverline(painter, overline); + else + painter->drawLine(overline); } painter->setPen(oldPen); @@ -6277,7 +6281,7 @@ Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t // 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. + // and do a drawTextItemDecoration call per cluster. if (i == 0 || baseLine < positions[i].y) baseLine = positions[i].y; @@ -6298,12 +6302,20 @@ Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), fontEngine, + 0, // textEngine font.underline() ? QTextCharFormat::SingleUnderline : QTextCharFormat::NoUnderline, flags, width.toReal(), charFormat); } -void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) +void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) +{ + Q_D(QPainter); + + d->drawTextItem(p, ti, static_cast<QTextEngine *>(0)); +} + +void QPainterPrivate::drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine) { #ifdef QT_DEBUG_DRAW if (qt_show_painter_debug_output) @@ -6311,35 +6323,35 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) p.x(), p.y(), qPrintable(_ti.text())); #endif - Q_D(QPainter); + Q_Q(QPainter); - if (!d->engine) + if (!engine) return; #ifndef QT_NO_DEBUG - qt_painter_thread_test(d->device->devType(), + qt_painter_thread_test(device->devType(), "text and fonts", QFontDatabase::supportsThreadedFontRendering()); #endif QTextItemInt &ti = const_cast<QTextItemInt &>(static_cast<const QTextItemInt &>(_ti)); - if (!d->extended && d->state->bgMode == Qt::OpaqueMode) { + if (!extended && state->bgMode == Qt::OpaqueMode) { QRectF rect(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()); - fillRect(rect, d->state->bgBrush); + q->fillRect(rect, state->bgBrush); } - if (pen().style() == Qt::NoPen) + if (q->pen().style() == Qt::NoPen) return; - const RenderHints oldRenderHints = d->state->renderHints; - if (!d->state->renderHints & QPainter::Antialiasing && d->state->matrix.type() >= QTransform::TxScale) { + const QPainter::RenderHints oldRenderHints = state->renderHints; + if (!state->renderHints & QPainter::Antialiasing && state->matrix.type() >= QTransform::TxScale) { // draw antialias decoration (underline/overline/strikeout) with // transformed text bool aa = true; - const QTransform &m = d->state->matrix; - if (d->state->matrix.type() < QTransform::TxShear) { + const QTransform &m = state->matrix; + if (state->matrix.type() < QTransform::TxShear) { bool isPlain90DegreeRotation = (qFuzzyIsNull(m.m11()) && qFuzzyIsNull(m.m12() - qreal(1)) @@ -6362,11 +6374,11 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) aa = !isPlain90DegreeRotation; } if (aa) - setRenderHint(QPainter::Antialiasing, true); + q->setRenderHint(QPainter::Antialiasing, true); } - if (!d->extended) - d->updateState(d->state); + if (!extended) + updateState(state); if (!ti.glyphs.numGlyphs) { // nothing to do @@ -6402,7 +6414,7 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) if (rtl) x -= ti2.width.toReal(); - d->engine->drawTextItem(QPointF(x, y), ti2); + engine->drawTextItem(QPointF(x, y), ti2); if (!rtl) x += ti2.width.toReal(); @@ -6429,10 +6441,10 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) if (rtl) x -= ti2.width.toReal(); - if (d->extended) - d->extended->drawTextItem(QPointF(x, y), ti2); + if (extended) + extended->drawTextItem(QPointF(x, y), ti2); else - d->engine->drawTextItem(QPointF(x,y), ti2); + engine->drawTextItem(QPointF(x,y), ti2); // reset the high byte for all glyphs const int hi = which << 24; @@ -6440,20 +6452,20 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) glyphs.glyphs[i] = hi | glyphs.glyphs[i]; } else { - if (d->extended) - d->extended->drawTextItem(p, ti); + if (extended) + extended->drawTextItem(p, ti); else - d->engine->drawTextItem(p, ti); + engine->drawTextItem(p, ti); } - drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(), - ti.charFormat); + drawTextItemDecoration(q, p, ti.fontEngine, textEngine, ti.underlineStyle, + ti.flags, ti.width.toReal(), ti.charFormat); - if (d->state->renderHints != oldRenderHints) { - d->state->renderHints = oldRenderHints; - if (d->extended) - d->extended->renderHintsChanged(); + if (state->renderHints != oldRenderHints) { + state->renderHints = oldRenderHints; + if (extended) + extended->renderHintsChanged(); else - d->state->dirtyFlags |= QPaintEngine::DirtyHints; + state->dirtyFlags |= QPaintEngine::DirtyHints; } } @@ -7550,11 +7562,12 @@ start_lengthVariant: for (int i = 0; i < textLayout.lineCount(); i++) { QTextLine line = textLayout.lineAt(i); + QTextEngine *eng = textLayout.engine(); + eng->enableDelayDecorations(); qreal advance = line.horizontalAdvance(); xoff = 0; if (tf & Qt::AlignRight) { - QTextEngine *eng = textLayout.engine(); xoff = r.width() - advance - eng->leadingSpaceWidth(eng->lines[line.lineNumber()]).toReal(); } @@ -7562,6 +7575,7 @@ start_lengthVariant: xoff = (r.width() - advance) / 2; line.draw(painter, QPointF(r.x() + xoff, r.y() + yoff)); + eng->drawDecorations(painter); } if (restore) { diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 67b05eeca5..97c10a2764 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -74,6 +74,7 @@ class QPainterPrivate; class QPen; class QPolygon; class QTextItem; +class QTextEngine; class QMatrix; class QTransform; class QStaticText; @@ -487,6 +488,7 @@ private: friend class QRasterPaintEngine; friend class QAlphaPaintEngine; friend class QPreviewPaintEngine; + friend class QTextEngine; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QPainter::RenderHints) diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index fecf8bd960..3327860ac9 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -230,6 +230,7 @@ public: void draw_helper(const QPainterPath &path, DrawOperation operation = StrokeAndFillDraw); void drawStretchedGradient(const QPainterPath &path, DrawOperation operation); void drawOpaqueBackground(const QPainterPath &path, DrawOperation operation); + void drawTextItem(const QPointF &p, const QTextItem &_ti, QTextEngine *textEngine); #if !defined(QT_NO_RAWFONT) void drawGlyphs(const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount, diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp index fb06a26c8f..a1deb47175 100644 --- a/src/gui/text/qdistancefield.cpp +++ b/src/gui/text/qdistancefield.cpp @@ -692,17 +692,8 @@ static QImage makeDistanceField(int imgSize, const QPainterPath &path, int dfSca return image; } -bool qt_fontHasNarrowOutlines(const QRawFont &f) +static bool imageHasNarrowOutlines(const QImage &im) { - QRawFont font = f; - font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE); - Q_ASSERT(font.isValid()); - - QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O")); - if (glyphIndices.size() < 1) - return false; - - QImage im = font.alphaMapForGlyph(glyphIndices.at(0), QRawFont::PixelAntialiasing); if (im.isNull()) return false; @@ -742,6 +733,56 @@ bool qt_fontHasNarrowOutlines(const QRawFont &f) return minHThick == 1 || minVThick == 1; } +bool qt_fontHasNarrowOutlines(QFontEngine *fontEngine) +{ + QFontEngine *fe = fontEngine->cloneWithSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE); + + QGlyphLayout glyphs; + glyph_t glyph; + glyphs.glyphs = &glyph; + int numGlyphs; + QChar *chars = QString(QLatin1String("O")).data(); + fe->stringToCMap(chars, 1, &glyphs, &numGlyphs, QTextEngine::GlyphIndicesOnly); + QImage im = fe->alphaMapForGlyph(glyph, QFixed(), QTransform()); + delete fe; + + return imageHasNarrowOutlines(im); +} + +bool qt_fontHasNarrowOutlines(const QRawFont &f) +{ + QRawFont font = f; + font.setPixelSize(QT_DISTANCEFIELD_DEFAULT_BASEFONTSIZE); + Q_ASSERT(font.isValid()); + + QVector<quint32> glyphIndices = font.glyphIndexesForString(QLatin1String("O")); + if (glyphIndices.size() < 1) + return false; + + return imageHasNarrowOutlines(font.alphaMapForGlyph(glyphIndices.at(0), + QRawFont::PixelAntialiasing)); +} + +static QImage renderDistanceFieldPath(const QPainterPath &path, bool doubleResolution) +{ + QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution), + path, + QT_DISTANCEFIELD_SCALE(doubleResolution), + QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution)); + return im; +} + +QImage qt_renderDistanceFieldGlyph(QFontEngine *fe, glyph_t glyph, bool doubleResolution) +{ + QFixedPoint position; + QPainterPath path; + fe->addGlyphsToPath(&glyph, &position, 1, &path, 0); + path.translate(-path.boundingRect().topLeft()); + path.setFillRule(Qt::WindingFill); + + return renderDistanceFieldPath(path, doubleResolution); +} + QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution) { QRawFont renderFont = font; @@ -751,11 +792,7 @@ QImage qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool dou path.translate(-path.boundingRect().topLeft()); path.setFillRule(Qt::WindingFill); - QImage im = makeDistanceField(QT_DISTANCEFIELD_TILESIZE(doubleResolution), - path, - QT_DISTANCEFIELD_SCALE(doubleResolution), - QT_DISTANCEFIELD_RADIUS(doubleResolution) / QT_DISTANCEFIELD_SCALE(doubleResolution)); - return im; + return renderDistanceFieldPath(path, doubleResolution); } QT_END_NAMESPACE diff --git a/src/gui/text/qdistancefield_p.h b/src/gui/text/qdistancefield_p.h index 486d291b78..bf87e7d3cb 100644 --- a/src/gui/text/qdistancefield_p.h +++ b/src/gui/text/qdistancefield_p.h @@ -79,6 +79,8 @@ QT_BEGIN_NAMESPACE bool Q_GUI_EXPORT qt_fontHasNarrowOutlines(const QRawFont &f); QImage Q_GUI_EXPORT qt_renderDistanceFieldGlyph(const QRawFont &font, glyph_t glyph, bool doubleResolution); +bool Q_GUI_EXPORT qt_fontHasNarrowOutlines(QFontEngine *fontEngine); +QImage Q_GUI_EXPORT qt_renderDistanceFieldGlyph(QFontEngine *fontEngine, glyph_t glyph, bool doubleResolution); QT_END_NAMESPACE diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index c68452d55a..56ff298d9b 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2733,20 +2733,6 @@ void QFontCache::updateHitCountAndTimeStamp(Engine &value) value.data->name()); } -void QFontCache::removeEngine(QFontEngine *engine) -{ - EngineCache::iterator it = engineCache.begin(); - while (it != engineCache.end()) { - if (it.value().data == engine) { - it = engineCache.erase(it); - if (--engine->cache_count == 0) - decreaseCost(engine->cache_cost); - } else { - ++it; - } - } -} - void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMulti) { FC_DEBUG("QFontCache: inserting new engine %p", engine); diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 06cf787880..13e5fcbedd 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -245,7 +245,6 @@ public: void updateHitCountAndTimeStamp(Engine &value); void insertEngine(const Key &key, QFontEngine *engine, bool insertMulti = false); - void removeEngine(QFontEngine *engine); private: void increaseCost(uint cost); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 142d627100..364a356b96 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -775,7 +775,7 @@ QByteArray QFontEngine::getSfntTable(uint tag) const return table; } -void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) +void QFontEngine::setGlyphCache(const void *key, QFontEngineGlyphCache *data) { Q_ASSERT(data); @@ -794,7 +794,7 @@ void QFontEngine::setGlyphCache(void *key, QFontEngineGlyphCache *data) } -QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const +QFontEngineGlyphCache *QFontEngine::glyphCache(const void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const { for (QLinkedList<GlyphCacheEntry>::const_iterator it = m_glyphCaches.constBegin(), end = m_glyphCaches.constEnd(); it != end; ++it) { QFontEngineGlyphCache *c = it->cache.data(); @@ -1421,22 +1421,6 @@ bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const return true; } -void QFontEngineMulti::unloadEngine(int at) -{ - QFontEngine *fontEngine = engines.at(at); - if (fontEngine == 0) - return; - - // If there are other references to the engine, keep it around and keep the reference - if (fontEngine->ref.load() == 1) { - QFontCache::instance()->removeEngine(fontEngine); - if (fontEngine->cache_count == 0) { - delete fontEngine; - engines[at] = 0; - } - } -} - glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs) { if (glyphs.numGlyphs <= 0) diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 660e3be459..1114cdf12c 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -239,8 +239,8 @@ public: virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); - void setGlyphCache(void *key, QFontEngineGlyphCache *data); - QFontEngineGlyphCache *glyphCache(void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const; + void setGlyphCache(const void *key, QFontEngineGlyphCache *data); + QFontEngineGlyphCache *glyphCache(const void *key, QFontEngineGlyphCache::Type type, const QTransform &transform) const; static const uchar *getCMap(const uchar *table, uint tableSize, bool *isSymbolFont, int *cmapSize); static quint32 getTrueTypeGlyphIndex(const uchar *cmap, uint unicode); @@ -284,7 +284,7 @@ protected: private: struct GlyphCacheEntry { - void *context; + const void *context; QExplicitlySharedDataPointer<QFontEngineGlyphCache> cache; bool operator==(const GlyphCacheEntry &other) const { return context == other.context && cache == other.cache; } }; @@ -401,7 +401,6 @@ protected: friend class QPSPrintEngineFontMulti; friend class QRawFont; virtual void loadEngine(int at) = 0; - virtual void unloadEngine(int at); QVector<QFontEngine *> engines; }; diff --git a/src/gui/text/qglyphrun.h b/src/gui/text/qglyphrun.h index 847b7e4852..b590775d8b 100644 --- a/src/gui/text/qglyphrun.h +++ b/src/gui/text/qglyphrun.h @@ -124,6 +124,8 @@ private: QExplicitlySharedDataPointer<QGlyphRunPrivate> d; }; +Q_DECLARE_TYPEINFO(QGlyphRun, Q_MOVABLE_TYPE); + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index dae02def07..3d58d91169 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1174,6 +1174,7 @@ static void init(QTextEngine *e) e->cacheGlyphs = false; e->forceJustification = false; e->visualMovement = false; + e->delayDecorations = false; e->layoutData = 0; @@ -2913,6 +2914,104 @@ int QTextEngine::positionAfterVisualMovement(int pos, QTextCursor::MoveOperation return pos; } +void QTextEngine::addItemDecoration(QPainter *painter, const QLineF &line, ItemDecorationList *decorationList) +{ + if (delayDecorations) { + decorationList->append(ItemDecoration(line.x1(), line.x2(), line.y1(), painter->pen())); + } else { + painter->drawLine(line); + } +} + +void QTextEngine::addUnderline(QPainter *painter, const QLineF &line) +{ + // qDebug() << "Adding underline:" << line; + addItemDecoration(painter, line, &underlineList); +} + +void QTextEngine::addStrikeOut(QPainter *painter, const QLineF &line) +{ + addItemDecoration(painter, line, &strikeOutList); +} + +void QTextEngine::addOverline(QPainter *painter, const QLineF &line) +{ + addItemDecoration(painter, line, &overlineList); +} + +void QTextEngine::drawItemDecorationList(QPainter *painter, const ItemDecorationList &decorationList) +{ + // qDebug() << "Drawing" << decorationList.size() << "decorations"; + if (decorationList.isEmpty()) + return; + + foreach (const ItemDecoration decoration, decorationList) { + painter->setPen(decoration.pen); + QLineF line(decoration.x1, decoration.y, decoration.x2, decoration.y); + painter->drawLine(line); + } +} + +void QTextEngine::drawDecorations(QPainter *painter) +{ + QPen oldPen = painter->pen(); + + adjustUnderlines(); + drawItemDecorationList(painter, underlineList); + drawItemDecorationList(painter, strikeOutList); + drawItemDecorationList(painter, overlineList); + + painter->setPen(oldPen); + clearDecorations(); +} + +void QTextEngine::clearDecorations() +{ + underlineList.clear(); + strikeOutList.clear(); + overlineList.clear(); +} + +void QTextEngine::adjustUnderlines() +{ + // qDebug() << __PRETTY_FUNCTION__ << underlineList.count() << "underlines"; + if (underlineList.isEmpty()) + return; + + ItemDecorationList::iterator start = underlineList.begin(); + ItemDecorationList::iterator end = underlineList.end(); + ItemDecorationList::iterator it = start; + qreal underlinePos = start->y; + qreal penWidth = start->pen.widthF(); + qreal lastLineEnd = start->x1; + + while (it != end) { + if (qFuzzyCompare(lastLineEnd, it->x1)) { // no gap between underlines + underlinePos = qMax(underlinePos, it->y); + penWidth = qMax(penWidth, it->pen.widthF()); + } else { // gap between this and the last underline + adjustUnderlines(start, it, underlinePos, penWidth); + start = it; + underlinePos = start->y; + penWidth = start->pen.widthF(); + } + lastLineEnd = it->x2; + ++it; + } + + adjustUnderlines(start, end, underlinePos, penWidth); +} + +void QTextEngine::adjustUnderlines(ItemDecorationList::iterator start, + ItemDecorationList::iterator end, + qreal underlinePos, qreal penWidth) +{ + for (ItemDecorationList::iterator it = start; it != end; ++it) { + it->y = underlinePos; + it->pen.setWidth(penWidth); + } +} + QStackTextEngine::QStackTextEngine(const QString &string, const QFont &f) : QTextEngine(string, f), _layoutData(string, _memory, MemSize) diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 6f1fd713f1..03581eb6a2 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -446,6 +446,18 @@ public: bool reallocate(int totalGlyphs); }; + struct ItemDecoration { + ItemDecoration(qreal x1, qreal x2, qreal y, const QPen &pen): + x1(x1), x2(x2), y(y), pen(pen) {} + + qreal x1; + qreal x2; + qreal y; + QPen pen; + }; + + typedef QList<ItemDecoration> ItemDecorationList; + QTextEngine(LayoutData *data); QTextEngine(); QTextEngine(const QString &str, const QFont &f); @@ -597,6 +609,7 @@ public: uint stackEngine : 1; uint forceJustification : 1; uint visualMovement : 1; + uint delayDecorations: 1; #ifndef QT_NO_RAWFONT uint useRawFont : 1; #endif @@ -605,6 +618,10 @@ public: mutable LayoutData *layoutData; + ItemDecorationList underlineList; + ItemDecorationList strikeOutList; + ItemDecorationList overlineList; + inline bool hasFormats() const { return (block.docHandle() || specialData); } inline bool visualCursorMovement() const { @@ -639,7 +656,22 @@ public: void insertionPointsForLine(int lineNum, QVector<int> &insertionPoints); void resetFontEngineCache(); + void enableDelayDecorations(bool enable = true) { delayDecorations = enable; } + + void addUnderline(QPainter *painter, const QLineF &line); + void addStrikeOut(QPainter *painter, const QLineF &line); + void addOverline(QPainter *painter, const QLineF &line); + + void drawDecorations(QPainter *painter); + void clearDecorations(); + void adjustUnderlines(); + private: + void addItemDecoration(QPainter *painter, const QLineF &line, ItemDecorationList *decorationList); + void adjustUnderlines(ItemDecorationList::iterator start, + ItemDecorationList::iterator end, + qreal underlinePos, qreal penWidth); + void drawItemDecorationList(QPainter *painter, const ItemDecorationList &decorationList); void setBoundary(int strPos) const; void addRequiredBoundaries() const; void shapeText(int item) const; diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index d5b05a8957..56098b0bdb 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -60,6 +60,7 @@ #include <qdebug.h> #include "qfontengine_p.h" +#include <private/qpainter_p.h> QT_BEGIN_NAMESPACE @@ -2062,7 +2063,7 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, if (rtl) x -= w; if (gf.num_chars) - p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf); + QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng); if (!rtl) x += w; if (ul && *ul != -1 && *ul < end) { @@ -2083,7 +2084,7 @@ static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, gf.underlineStyle = QTextCharFormat::SingleUnderline; if (rtl) x -= w; - p->drawTextItem(QPointF(x.toReal(), y.toReal()), gf); + QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng); if (!rtl) x += w; gf.underlineStyle = QTextCharFormat::NoUnderline; @@ -2379,6 +2380,8 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR QTextLineItemIterator iterator(eng, index, pos, selection); QFixed lineBase = line.base(); + eng->clearDecorations(); + eng->enableDelayDecorations(); const QFixed y = QFixed::fromReal(pos.y()) + line.y + lineBase; @@ -2451,7 +2454,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR gf.chars = 0; gf.num_chars = 0; gf.width = iterator.itemWidth; - p->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf); + QPainterPrivate::get(p)->drawTextItem(QPointF(iterator.x.toReal(), y.toReal()), gf, eng); if (eng->option.flags() & QTextOption::ShowTabsAndSpaces) { QChar visualTab(0x2192); int w = QFontMetrics(f).width(visualTab); @@ -2529,7 +2532,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR } else { if (noText) gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be - p->drawTextItem(pos, gf); + QPainterPrivate::get(p)->drawTextItem(pos, gf, eng); } } if (si.analysis.flags == QScriptAnalysis::Space @@ -2542,7 +2545,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR p->setPen(pen); } } - + eng->drawDecorations(p); if (eng->hasFormats()) p->setPen(pen); |