diff options
Diffstat (limited to 'src/gui')
68 files changed, 1019 insertions, 303 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index 86ed4c3a71..b7f341d5b7 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -17,5 +17,9 @@ contains(QT_CONFIG, accessibility) { HEADERS += accessible/qaccessiblebridge.h SOURCES += accessible/qaccessiblebridge.cpp - OBJECTIVE_SOURCES += accessible/qaccessiblecache_mac.mm + mac { + OBJECTIVE_SOURCES += accessible/qaccessiblecache_mac.mm + + LIBS_PRIVATE += -framework Foundation + } } diff --git a/src/gui/gui.pro b/src/gui/gui.pro index aa05d72a3d..55837bcf3b 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -33,7 +33,7 @@ testcocoon { load(testcocoon) } -mac:!ios: LIBS_PRIVATE += -framework Cocoa +osx: LIBS_PRIVATE += -framework AppKit CONFIG += simd optimize_full diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index d9e1347e4b..ca77b73033 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -920,7 +920,7 @@ void QIcon::paint(QPainter *painter, const QRect &rect, Qt::Alignment alignment, */ bool QIcon::isNull() const { - return !d; + return !d || d->engine->isNull(); } /*!\internal @@ -935,7 +935,12 @@ bool QIcon::isDetached() const void QIcon::detach() { if (d) { - if (d->ref.load() != 1) { + if (d->engine->isNull()) { + if (!d->ref.deref()) + delete d; + d = 0; + return; + } else if (d->ref.load() != 1) { QIconPrivate *x = new QIconPrivate; x->engine = d->engine->clone(); if (!d->ref.deref()) @@ -959,11 +964,10 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) { if (pixmap.isNull()) return; + detach(); if (!d) { d = new QIconPrivate; d->engine = new QPixmapIconEngine; - } else { - detach(); } d->engine->addPixmap(pixmap, mode, state); } @@ -1003,6 +1007,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State { if (fileName.isEmpty()) return; + detach(); if (!d) { #ifndef QT_NO_LIBRARY QFileInfo info(fileName); @@ -1025,8 +1030,6 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State d = new QIconPrivate; d->engine = new QPixmapIconEngine; } - } else { - detach(); } d->engine->addFile(fileName, size, mode, state); @@ -1136,8 +1139,7 @@ QString QIcon::themeName() \since 4.6 Returns the QIcon corresponding to \a name in the current - icon theme. If no such icon is found in the current theme - \a fallback is returned instead. + icon theme. The latest version of the freedesktop icon specification and naming specification can be obtained here: @@ -1151,19 +1153,18 @@ QString QIcon::themeName() \snippet code/src_gui_image_qicon.cpp 3 - Or if you want to provide a guaranteed fallback for platforms that - do not support theme icons, you can use the second argument: - - \snippet code/src_gui_image_qicon.cpp 4 - \note By default, only X11 will support themed icons. In order to use themed icons on Mac and Windows, you will have to bundle a compliant theme in one of your themeSearchPaths() and set the appropriate themeName(). + \note Qt will make use of GTK's icon-theme.cache if present to speed up + the lookup. These caches can be generated using gtk-update-icon-cache: + \l{https://developer.gnome.org/gtk3/stable/gtk-update-icon-cache.html}. + \sa themeName(), setThemeName(), themeSearchPaths() */ -QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) +QIcon QIcon::fromTheme(const QString &name) { QIcon icon; @@ -1179,7 +1180,26 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) qtIconCache()->insert(name, cachedIcon); } - if (qApp && icon.availableSizes().isEmpty()) + return icon; +} + +/*! + \overload + + Returns the QIcon corresponding to \a name in the current + icon theme. If no such icon is found in the current theme + \a fallback is returned instead. + + If you want to provide a guaranteed fallback for platforms that + do not support theme icons, you can use the second argument: + + \snippet code/src_gui_image_qicon.cpp 4 +*/ +QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) +{ + QIcon icon = fromTheme(name); + + if (icon.isNull() || icon.availableSizes().isEmpty()) return fallback; return icon; diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 9ed7336502..989e40bbb5 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -105,7 +105,8 @@ public: void setIsMask(bool isMask); bool isMask() const; - static QIcon fromTheme(const QString &name, const QIcon &fallback = QIcon()); + static QIcon fromTheme(const QString &name); + static QIcon fromTheme(const QString &name, const QIcon &fallback); static bool hasThemeIcon(const QString &name); static QStringList themeSearchPaths(); diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index c09933d45f..7411dbb054 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -150,6 +150,11 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI icon, for example when instantiating an icon using QIcon::fromTheme(). + \value IsNullHook Allow to query if this engine represents a null + icon. The \a data argument of the virtual_hook() is a pointer to a + bool that can be set to true if the icon is null. This enum value + was added in Qt 5.7. + \sa virtual_hook() */ @@ -283,4 +288,16 @@ QString QIconEngine::iconName() const return name; } +/*! + \since 5.7 + + Returns true if this icon engine represent a null QIcon. + */ +bool QIconEngine::isNull() const +{ + bool isNull = false; + const_cast<QIconEngine *>(this)->virtual_hook(QIconEngine::IsNullHook, &isNull); + return isNull; +} + QT_END_NAMESPACE diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 9977113054..6c45cd216f 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -58,7 +58,7 @@ public: virtual bool read(QDataStream &in); virtual bool write(QDataStream &out) const; - enum IconEngineHook { AvailableSizesHook = 1, IconNameHook }; + enum IconEngineHook { AvailableSizesHook = 1, IconNameHook, IsNullHook }; struct AvailableSizesArgument { @@ -71,6 +71,7 @@ public: QIcon::State state = QIcon::Off) const; virtual QString iconName() const; + bool isNull() const; // ### Qt6 make virtual virtual void virtual_hook(int id, void *data); }; diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index 3ead72dfbb..ecce7f9967 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -155,6 +155,141 @@ QStringList QIconLoader::themeSearchPaths() const return m_iconDirs; } +/*! + \class QIconCacheGtkReader + \internal + Helper class that reads and looks up into the icon-theme.cache generated with + gtk-update-icon-cache. If at any point we detect a corruption in the file + (because the offsets point at wrong locations for example), the reader + is marked as invalid. +*/ +class QIconCacheGtkReader +{ +public: + explicit QIconCacheGtkReader(const QString &themeDir); + QVector<const char *> lookup(const QString &); + bool isValid() const { return m_isValid; } +private: + QFile m_file; + const unsigned char *m_data; + quint64 m_size; + bool m_isValid; + + quint16 read16(uint offset) + { + if (offset > m_size - 2 || (offset & 0x1)) { + m_isValid = false; + return 0; + } + return m_data[offset+1] | m_data[offset] << 8; + } + quint32 read32(uint offset) + { + if (offset > m_size - 4 || (offset & 0x3)) { + m_isValid = false; + return 0; + } + return m_data[offset+3] | m_data[offset+2] << 8 + | m_data[offset+1] << 16 | m_data[offset] << 24; + } +}; + + +QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName) + : m_isValid(false) +{ + QFileInfo info(dirName + QLatin1Literal("/icon-theme.cache")); + if (!info.exists() || info.lastModified() < QFileInfo(dirName).lastModified()) + return; + m_file.setFileName(info.absoluteFilePath()); + if (!m_file.open(QFile::ReadOnly)) + return; + m_size = m_file.size(); + m_data = m_file.map(0, m_size); + if (!m_data) + return; + if (read16(0) != 1) // VERSION_MAJOR + return; + + m_isValid = true; + + // Check that all the directories are older than the cache + auto lastModified = info.lastModified(); + quint32 dirListOffset = read32(8); + quint32 dirListLen = read32(dirListOffset); + for (uint i = 0; i < dirListLen; ++i) { + quint32 offset = read32(dirListOffset + 4 + 4 * i); + if (!m_isValid || offset >= m_size || lastModified < QFileInfo(dirName + QLatin1Char('/') + + QString::fromUtf8(reinterpret_cast<const char*>(m_data + offset))).lastModified()) { + m_isValid = false; + return; + } + } +} + +static quint32 icon_name_hash(const char *p) +{ + quint32 h = static_cast<signed char>(*p); + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + *p; + return h; +} + +/*! \internal + lookup the icon name and return the list of subdirectories in which an icon + with this name is present. The char* are pointers to the mapped data. + For example, this would return { "32x32/apps", "24x24/apps" , ... } + */ +QVector<const char *> QIconCacheGtkReader::lookup(const QString &name) +{ + QVector<const char *> ret; + if (!isValid()) + return ret; + + QByteArray nameUtf8 = name.toUtf8(); + quint32 hash = icon_name_hash(nameUtf8); + + quint32 hashOffset = read32(4); + quint32 hashBucketCount = read32(hashOffset); + + if (!isValid() || hashBucketCount == 0) { + m_isValid = false; + return ret; + } + + quint32 bucketIndex = hash % hashBucketCount; + quint32 bucketOffset = read32(hashOffset + 4 + bucketIndex * 4); + while (bucketOffset > 0 && bucketOffset <= m_size - 12) { + quint32 nameOff = read32(bucketOffset + 4); + if (nameOff < m_size && strcmp(reinterpret_cast<const char*>(m_data + nameOff), nameUtf8) == 0) { + quint32 dirListOffset = read32(8); + quint32 dirListLen = read32(dirListOffset); + + quint32 listOffset = read32(bucketOffset+8); + quint32 listLen = read32(listOffset); + + if (!m_isValid || listOffset + 4 + 8 * listLen > m_size) { + m_isValid = false; + return ret; + } + + ret.reserve(listLen); + for (uint j = 0; j < listLen && m_isValid; ++j) { + quint32 dirIndex = read16(listOffset + 4 + 8 * j); + quint32 o = read32(dirListOffset + 4 + dirIndex*4); + if (!m_isValid || dirIndex >= dirListLen || o >= m_size) { + m_isValid = false; + return ret; + } + ret.append(reinterpret_cast<const char*>(m_data) + o); + } + return ret; + } + bucketOffset = read32(bucketOffset); + } + return ret; +} + QIconTheme::QIconTheme(const QString &themeName) : m_valid(false) { @@ -166,8 +301,10 @@ QIconTheme::QIconTheme(const QString &themeName) QString themeDir = iconDir.path() + QLatin1Char('/') + themeName; QFileInfo themeDirInfo(themeDir); - if (themeDirInfo.isDir()) + if (themeDirInfo.isDir()) { m_contentDirs << themeDir; + m_gtkCaches << QSharedPointer<QIconCacheGtkReader>::create(themeDir); + } if (!m_valid) { themeIndex.setFileName(themeDir + QLatin1String("/index.theme")); @@ -257,7 +394,6 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, } const QStringList contentDirs = theme.contentDirs(); - const QVector<QIconDirInfo> subDirs = theme.keyList(); QString iconNameFallback = iconName; @@ -268,6 +404,29 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName, // Add all relevant files for (int i = 0; i < contentDirs.size(); ++i) { + QVector<QIconDirInfo> subDirs = theme.keyList(); + + // Try to reduce the amount of subDirs by looking in the GTK+ cache in order to save + // a massive amount of file stat (especially if the icon is not there) + auto cache = theme.m_gtkCaches.at(i); + if (cache->isValid()) { + auto result = cache->lookup(iconNameFallback); + if (cache->isValid()) { + const QVector<QIconDirInfo> subDirsCopy = subDirs; + subDirs.clear(); + subDirs.reserve(result.count()); + foreach (const char *s, result) { + QString path = QString::fromUtf8(s); + auto it = std::find_if(subDirsCopy.cbegin(), subDirsCopy.cend(), + [&](const QIconDirInfo &info) { + return info.path == path; } ); + if (it != subDirsCopy.cend()) { + subDirs.append(*it); + } + } + } + } + QString contentDir = contentDirs.at(i) + QLatin1Char('/'); for (int j = 0; j < subDirs.size() ; ++j) { const QIconDirInfo &dirInfo = subDirs.at(j); @@ -587,6 +746,11 @@ void QIconLoaderEngine::virtual_hook(int id, void *data) name = m_info.iconName; } break; + case QIconEngine::IsNullHook: + { + *reinterpret_cast<bool*>(data) = m_info.entries.isEmpty(); + } + break; default: QIconEngine::virtual_hook(id, data); } diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index ccf0a9d438..193154e44e 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -139,6 +139,8 @@ private: friend class QIconLoader; }; +class QIconCacheGtkReader; + class QIconTheme { public: @@ -148,12 +150,13 @@ public: QVector<QIconDirInfo> keyList() { return m_keyList; } QStringList contentDirs() { return m_contentDirs; } bool isValid() { return m_valid; } - private: QStringList m_contentDirs; QVector<QIconDirInfo> m_keyList; QStringList m_parents; bool m_valid; +public: + QVector<QSharedPointer<QIconCacheGtkReader>> m_gtkCaches; }; class Q_GUI_EXPORT QIconLoader diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 888c7beb32..9d8e3efcc4 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -168,9 +168,9 @@ public: Format format() const; #if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QIMAGE_COMPAT_CPP) - QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const & Q_REQUIRED_RESULT + Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) const & Q_REQUIRED_RESULT { return convertToFormat_helper(f, flags); } - QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) && Q_REQUIRED_RESULT + Q_ALWAYS_INLINE QImage convertToFormat(Format f, Qt::ImageConversionFlags flags = Qt::AutoColor) && Q_REQUIRED_RESULT { if (convertToFormat_inplace(f, flags)) return std::move(*this); diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index 09cd788c61..ba27fb355b 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -965,14 +965,16 @@ void QMovie::setScaledSize(const QSize &size) QList<QByteArray> QMovie::supportedFormats() { QList<QByteArray> list = QImageReader::supportedImageFormats(); - QMutableListIterator<QByteArray> it(list); + QBuffer buffer; buffer.open(QIODevice::ReadOnly); - while (it.hasNext()) { - QImageReader reader(&buffer, it.next()); - if (!reader.supportsAnimation()) - it.remove(); - } + + const auto doesntSupportAnimation = + [&buffer](const QByteArray &format) { + return !QImageReader(&buffer, format).supportsAnimation(); + }; + + list.erase(std::remove_if(list.begin(), list.end(), doesntSupportAnimation), list.end()); return list; } diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index fb62889e40..9c42cd44a6 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE static bool qt_pixmap_thread_test() { - if (!QCoreApplication::instance()) { + if (Q_UNLIKELY(!QCoreApplication::instance())) { qFatal("QPixmap: Must construct a QGuiApplication before a QPixmap"); return false; } diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index d29ddcf978..6265a0c16d 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -156,6 +156,16 @@ bool QPixmapCache::Key::operator ==(const Key &key) const */ /*! + Returns \c true if there is a cached pixmap associated with this key. + Otherwise, if pixmap was flushed, the key is no longer valid. + \since 5.7 +*/ +bool QPixmapCache::Key::isValid() const Q_DECL_NOTHROW +{ + return d && d->isValid; +} + +/*! \internal */ QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other) diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index 37a0588e06..ca18f299a7 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -59,6 +59,7 @@ public: Key &operator =(const Key &other); void swap(Key &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + bool isValid() const Q_DECL_NOTHROW; private: KeyData *d; diff --git a/src/gui/kernel/qdrag.cpp b/src/gui/kernel/qdrag.cpp index 2736fac8e0..36527966b7 100644 --- a/src/gui/kernel/qdrag.cpp +++ b/src/gui/kernel/qdrag.cpp @@ -33,6 +33,8 @@ #include <qdrag.h> #include "private/qguiapplication_p.h" +#include "qpa/qplatformintegration.h" +#include "qpa/qplatformdrag.h" #include <qpixmap.h> #include <qpoint.h> #include "qdnd_p.h" @@ -223,6 +225,8 @@ QObject *QDrag::target() const loop. Other events are still delivered to the application while the operation is performed. On Windows, the Qt event loop is blocked during the operation. + + \sa cancel() */ Qt::DropAction QDrag::exec(Qt::DropActions supportedActions) @@ -377,6 +381,21 @@ Qt::DropAction QDrag::defaultAction() const Q_D(const QDrag); return d->default_action; } + +/*! + Cancels a drag operation initiated by Qt. + + \note This is currently implemented on Windows and X11. + + \since 5.6 + \sa exec() +*/ +void QDrag::cancel() +{ + if (QPlatformDrag *platformDrag = QGuiApplicationPrivate::platformIntegration()->drag()) + platformDrag->cancelDrag(); +} + /*! \fn void QDrag::actionChanged(Qt::DropAction action) diff --git a/src/gui/kernel/qdrag.h b/src/gui/kernel/qdrag.h index 0672cb00f9..961d7c89d9 100644 --- a/src/gui/kernel/qdrag.h +++ b/src/gui/kernel/qdrag.h @@ -77,6 +77,8 @@ public: Qt::DropActions supportedActions() const; Qt::DropAction defaultAction() const; + static void cancel(); + Q_SIGNALS: void actionChanged(Qt::DropAction action); void targetChanged(QObject *newTarget); diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2ca17692db..bd1b4d6393 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -37,6 +37,7 @@ #include "qpa/qplatformintegration.h" #include "qpa/qplatformdrag.h" #include "private/qevent_p.h" +#include "qfile.h" #include "qmetaobject.h" #include "qmimedata.h" #include "private/qdnd_p.h" @@ -3963,9 +3964,11 @@ QDebug operator<<(QDebug dbg, const QEvent *e) QtDebugUtils::formatQEnum(dbg, static_cast<const QApplicationStateChangeEvent *>(e)->applicationState()); dbg << ')'; break; +# ifndef QT_NO_CONTEXTMENU case QEvent::ContextMenu: dbg << "QContextMenuEvent(" << static_cast<const QContextMenuEvent *>(e)->pos() << ')'; break; +# endif // !QT_NO_CONTEXTMENU # ifndef QT_NO_TABLETEVENT case QEvent::TabletEnterProximity: case QEvent::TabletLeaveProximity: diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index b90fce97e0..cd65485397 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -35,20 +35,19 @@ #define QEVENT_H #include <QtGui/qwindowdefs.h> -#include <QtCore/qobject.h> #include <QtGui/qregion.h> #include <QtCore/qnamespace.h> #include <QtCore/qstring.h> #include <QtGui/qkeysequence.h> #include <QtCore/qcoreevent.h> #include <QtCore/qvariant.h> -#include <QtCore/qmap.h> +#include <QtCore/qmap.h> // ### Qt 6: Remove #include <QtCore/qvector.h> -#include <QtCore/qset.h> +#include <QtCore/qset.h> // ### Qt 6: Remove #include <QtCore/qurl.h> -#include <QtCore/qfile.h> +#include <QtCore/qfile.h> // ### Qt 6: Replace by <qiodevice.h> and forward declare QFile #include <QtGui/qvector2d.h> -#include <QtGui/qtouchdevice.h> +#include <QtGui/qtouchdevice.h> // ### Qt 6: Replace by forward declaration QT_BEGIN_NAMESPACE @@ -909,6 +908,9 @@ protected: friend class QGuiApplicationPrivate; friend class QApplication; friend class QApplicationPrivate; +#ifndef QT_NO_GRAPHICSVIEW + friend class QGraphicsScenePrivate; // direct access to _touchPoints +#endif }; Q_DECLARE_TYPEINFO(QTouchEvent::TouchPoint, Q_MOVABLE_TYPE); Q_DECLARE_OPERATORS_FOR_FLAGS(QTouchEvent::TouchPoint::InfoFlags) diff --git a/src/gui/kernel/qgenericplugin.cpp b/src/gui/kernel/qgenericplugin.cpp index 47f3ea5811..ae423b93e3 100644 --- a/src/gui/kernel/qgenericplugin.cpp +++ b/src/gui/kernel/qgenericplugin.cpp @@ -33,8 +33,6 @@ #include "qgenericplugin.h" -#ifndef QT_NO_LIBRARY - QT_BEGIN_NAMESPACE /*! @@ -90,5 +88,3 @@ QGenericPlugin::~QGenericPlugin() */ QT_END_NAMESPACE - -#endif // QT_NO_LIBRARY diff --git a/src/gui/kernel/qgenericplugin.h b/src/gui/kernel/qgenericplugin.h index 03c1df7fba..21ae97f045 100644 --- a/src/gui/kernel/qgenericplugin.h +++ b/src/gui/kernel/qgenericplugin.h @@ -39,9 +39,6 @@ QT_BEGIN_NAMESPACE - -#ifndef QT_NO_LIBRARY - #define QGenericPluginFactoryInterface_iid "org.qt-project.Qt.QGenericPluginFactoryInterface" class Q_GUI_EXPORT QGenericPlugin : public QObject @@ -54,8 +51,6 @@ public: virtual QObject* create(const QString& name, const QString &spec) = 0; }; -#endif // QT_NO_LIBRARY - QT_END_NAMESPACE #endif // QGENERICPLUGIN_H diff --git a/src/gui/kernel/qgenericpluginfactory.cpp b/src/gui/kernel/qgenericpluginfactory.cpp index d7b9bfba06..15fa094f54 100644 --- a/src/gui/kernel/qgenericpluginfactory.cpp +++ b/src/gui/kernel/qgenericpluginfactory.cpp @@ -71,7 +71,7 @@ QObject *QGenericPluginFactory::create(const QString& key, const QString &specif { #if (!defined(Q_OS_WIN32) || defined(QT_SHARED)) && !defined(QT_NO_LIBRARY) const QString driver = key.toLower(); - if (QObject *object = qLoadPlugin1<QObject, QGenericPlugin>(loader(), driver, specification)) + if (QObject *object = qLoadPlugin<QObject, QGenericPlugin>(loader(), driver, specification)) return object; #else // (!Q_OS_WIN32 || QT_SHARED) && !QT_NO_LIBRARY Q_UNUSED(key) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 770f847190..777ecbdb09 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -37,6 +37,7 @@ #include <qpa/qplatformintegrationfactory_p.h> #include "private/qevent_p.h" #include "qfont.h" +#include "qtouchdevice.h" #include <qpa/qplatformfontdatabase.h> #include <qpa/qplatformwindow.h> #include <qpa/qplatformnativeinterface.h> @@ -123,8 +124,6 @@ Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier; QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf()); -Qt::MouseButtons QGuiApplicationPrivate::tabletState = Qt::NoButton; -QWindow *QGuiApplicationPrivate::tabletPressTarget = 0; QWindow *QGuiApplicationPrivate::currentMouseWindow = 0; QString QGuiApplicationPrivate::styleOverride; @@ -133,6 +132,8 @@ Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationI bool QGuiApplicationPrivate::highDpiScalingUpdated = false; +QVector<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints; + QPlatformIntegration *QGuiApplicationPrivate::platform_integration = 0; QPlatformTheme *QGuiApplicationPrivate::platform_theme = 0; @@ -150,6 +151,7 @@ QIcon *QGuiApplicationPrivate::app_icon = 0; QString *QGuiApplicationPrivate::platform_name = 0; QString *QGuiApplicationPrivate::displayName = 0; +QString *QGuiApplicationPrivate::desktopFileName = 0; QPalette *QGuiApplicationPrivate::app_pal = 0; // default application palette @@ -607,6 +609,8 @@ QGuiApplication::~QGuiApplication() QGuiApplicationPrivate::platform_name = 0; delete QGuiApplicationPrivate::displayName; QGuiApplicationPrivate::displayName = 0; + delete QGuiApplicationPrivate::desktopFileName; + QGuiApplicationPrivate::desktopFileName = 0; } QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags) @@ -648,6 +652,34 @@ QString QGuiApplication::applicationDisplayName() } /*! + \property QGuiApplication::desktopFileName + \brief the base name of the desktop entry for this application + \since 5.7 + + This is the file name, without the full path, of the desktop entry + that represents this application according to the freedesktop desktop + entry specification. + + This property gives a precise indication of what desktop entry represents + the application and it is needed by the windowing system to retrieve + such information without resorting to imprecise heuristics. + + The latest version of the freedesktop desktop entry specification can be obtained + \l{http://standards.freedesktop.org/desktop-entry-spec/latest/}{here}. +*/ +void QGuiApplication::setDesktopFileName(const QString &name) +{ + if (!QGuiApplicationPrivate::desktopFileName) + QGuiApplicationPrivate::desktopFileName = new QString; + *QGuiApplicationPrivate::desktopFileName = name; +} + +QString QGuiApplication::desktopFileName() +{ + return QGuiApplicationPrivate::desktopFileName ? *QGuiApplicationPrivate::desktopFileName : QString(); +} + +/*! Returns the most recently shown modal window. If no modal windows are visible, this function returns zero. @@ -1050,9 +1082,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform // Create the platform integration. QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath); - if (QGuiApplicationPrivate::platform_integration) { - QGuiApplicationPrivate::platform_name = new QString(name); - } else { + if (Q_UNLIKELY(!QGuiApplicationPrivate::platform_integration)) { QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath); QString fatalMessage @@ -1072,6 +1102,8 @@ static void init_platform(const QString &pluginArgument, const QString &platform return; } + QGuiApplicationPrivate::platform_name = new QString(name); + // Many platforms have created QScreens at this point. Finish initializing // QHighDpiScaling to be prepared for early calls to qt_defaultDpi(). if (QGuiApplication::primaryScreen()) { @@ -1391,16 +1423,16 @@ void QGuiApplicationPrivate::init() if (loadTestability) { QLibrary testLib(QStringLiteral("qttestability")); - if (testLib.load()) { + if (Q_UNLIKELY(!testLib.load())) { + qCritical() << "Library qttestability load failed:" << testLib.errorString(); + } else { typedef void (*TasInitialize)(void); TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); - if (initFunction) { - initFunction(); - } else { + if (Q_UNLIKELY(!initFunction)) { qCritical() << "Library qttestability resolve failed!"; + } else { + initFunction(); } - } else { - qCritical() << "Library qttestability load failed:" << testLib.errorString(); } } #else @@ -2180,12 +2212,26 @@ void QGuiApplicationPrivate::processFileOpenEvent(QWindowSystemInterfacePrivate: QGuiApplication::sendSpontaneousEvent(qApp, &event); } +QGuiApplicationPrivate::TabletPointData &QGuiApplicationPrivate::tabletDevicePoint(qint64 deviceId) +{ + for (int i = 0; i < tabletDevicePoints.size(); ++i) { + TabletPointData &pointData = tabletDevicePoints[i]; + if (pointData.deviceId == deviceId) + return pointData; + } + + tabletDevicePoints.append(TabletPointData(deviceId)); + return tabletDevicePoints.last(); +} + void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::TabletEvent *e) { #ifndef QT_NO_TABLETEVENT + TabletPointData &pointData = tabletDevicePoint(e->uid); + QEvent::Type type = QEvent::TabletMove; - if (e->buttons != tabletState) - type = (e->buttons > tabletState) ? QEvent::TabletPress : QEvent::TabletRelease; + if (e->buttons != pointData.state) + type = (e->buttons > pointData.state) ? QEvent::TabletPress : QEvent::TabletRelease; QWindow *window = e->window.data(); modifier_buttons = e->modifiers; @@ -2201,14 +2247,14 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T } if (!window) return; - tabletPressTarget = window; + pointData.target = window; } else { if (e->nullWindow()) { - window = tabletPressTarget; + window = pointData.target; localValid = false; } if (type == QEvent::TabletRelease) - tabletPressTarget = 0; + pointData.target = Q_NULLPTR; if (!window) return; } @@ -2217,7 +2263,7 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T QPointF delta = e->global - e->global.toPoint(); local = window->mapFromGlobal(e->global.toPoint()) + delta; } - Qt::MouseButtons stateChange = e->buttons ^ tabletState; + Qt::MouseButtons stateChange = e->buttons ^ pointData.state; Qt::MouseButton button = Qt::NoButton; for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) { if (check & stateChange) { @@ -2231,7 +2277,7 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T e->modifiers, e->uid, button, e->buttons); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); - tabletState = e->buttons; + pointData.state = e->buttons; #else Q_UNUSED(e) #endif @@ -2243,7 +2289,7 @@ void QGuiApplicationPrivate::processTabletEnterProximityEvent(QWindowSystemInter QTabletEvent ev(QEvent::TabletEnterProximity, QPointF(), QPointF(), e->device, e->pointerType, 0, 0, 0, 0, 0, 0, - Qt::NoModifier, e->uid, Qt::NoButton, tabletState); + Qt::NoModifier, e->uid, Qt::NoButton, tabletDevicePoint(e->uid).state); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -2257,7 +2303,7 @@ void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInter QTabletEvent ev(QEvent::TabletLeaveProximity, QPointF(), QPointF(), e->device, e->pointerType, 0, 0, 0, 0, 0, 0, - Qt::NoModifier, e->uid, Qt::NoButton, tabletState); + Qt::NoModifier, e->uid, Qt::NoButton, tabletDevicePoint(e->uid).state); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -3542,7 +3588,7 @@ void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object) emit q->focusObjectChanged(object); } -enum { +enum MouseMasks { MouseCapsMask = 0xFF, MouseSourceMaskDst = 0xFF00, MouseSourceMaskSrc = MouseCapsMask, diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h index d995387d66..a773122d3e 100644 --- a/src/gui/kernel/qguiapplication.h +++ b/src/gui/kernel/qguiapplication.h @@ -67,6 +67,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication Q_OBJECT Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon) Q_PROPERTY(QString applicationDisplayName READ applicationDisplayName WRITE setApplicationDisplayName) + Q_PROPERTY(QString desktopFileName READ desktopFileName WRITE setDesktopFileName) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(QString platformName READ platformName STORED false) Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed WRITE setQuitOnLastWindowClosed) @@ -83,6 +84,9 @@ public: static void setApplicationDisplayName(const QString &name); static QString applicationDisplayName(); + static void setDesktopFileName(const QString &name); + static QString desktopFileName(); + static QWindowList allWindows(); static QWindowList topLevelWindows(); static QWindow *topLevelAt(const QPoint &pos); diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 7c7da9790b..5ef8dee8b7 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -183,6 +183,7 @@ public: static QIcon *app_icon; static QString *platform_name; static QString *displayName; + static QString *desktopFileName; QWindowList modalWindowList; static void showModalWindow(QWindow *window); @@ -197,13 +198,20 @@ public: static int mousePressY; static int mouse_double_click_distance; static QPointF lastCursorPosition; - static Qt::MouseButtons tabletState; - static QWindow *tabletPressTarget; static QWindow *currentMouseWindow; static QWindow *currentMousePressWindow; static Qt::ApplicationState applicationState; static bool highDpiScalingUpdated; + struct TabletPointData { + TabletPointData(qint64 devId = 0) : deviceId(devId), state(Qt::NoButton), target(Q_NULLPTR) {} + qint64 deviceId; + Qt::MouseButtons state; + QWindow *target; + }; + static QVector<TabletPointData> tabletDevicePoints; + static TabletPointData &tabletDevicePoint(qint64 deviceId); + #ifndef QT_NO_CLIPBOARD static QClipboard *qt_clipboard; #endif diff --git a/src/gui/kernel/qinputdevicemanager_p.h b/src/gui/kernel/qinputdevicemanager_p.h index d64793c23c..4c24b1bc93 100644 --- a/src/gui/kernel/qinputdevicemanager_p.h +++ b/src/gui/kernel/qinputdevicemanager_p.h @@ -61,7 +61,8 @@ public: DeviceTypeUnknown, DeviceTypePointer, DeviceTypeKeyboard, - DeviceTypeTouch + DeviceTypeTouch, + DeviceTypeTablet }; QInputDeviceManager(QObject *parent = 0); diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 3c033ea39e..8258e3999c 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -948,7 +948,7 @@ bool QOpenGLContext::makeCurrent(QSurface *surface) if (!isValid()) return false; - if (thread() != QThread::currentThread()) + if (Q_UNLIKELY(thread() != QThread::currentThread())) qFatal("Cannot make QOpenGLContext current in a different thread"); if (!surface) { diff --git a/src/gui/kernel/qplatformdrag.cpp b/src/gui/kernel/qplatformdrag.cpp index d789c75d1d..11230194fc 100644 --- a/src/gui/kernel/qplatformdrag.cpp +++ b/src/gui/kernel/qplatformdrag.cpp @@ -155,6 +155,20 @@ Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, } /*! + \brief Cancels the currently active drag (only for drags of + the current application initiated by QPlatformDrag::drag()). + + The default implementation does nothing. + + \since 5.6 + */ + +void QPlatformDrag::cancelDrag() +{ + Q_UNIMPLEMENTED(); +} + +/*! \brief Called to notify QDrag about changes of the current action. */ diff --git a/src/gui/kernel/qplatformdrag.h b/src/gui/kernel/qplatformdrag.h index 10ee88477f..72e28d2745 100644 --- a/src/gui/kernel/qplatformdrag.h +++ b/src/gui/kernel/qplatformdrag.h @@ -92,6 +92,7 @@ public: virtual QMimeData *platformDropData() = 0; virtual Qt::DropAction drag(QDrag *m_drag) = 0; + virtual void cancelDrag(); void updateAction(Qt::DropAction action); virtual Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const; diff --git a/src/gui/kernel/qplatforminputcontextfactory.cpp b/src/gui/kernel/qplatforminputcontextfactory.cpp index fedf940dda..c80797d884 100644 --- a/src/gui/kernel/qplatforminputcontextfactory.cpp +++ b/src/gui/kernel/qplatforminputcontextfactory.cpp @@ -69,7 +69,7 @@ QPlatformInputContext *QPlatformInputContextFactory::create(const QString& key) QStringList paramList = key.split(QLatin1Char(':')); const QString platform = paramList.takeFirst().toLower(); - QPlatformInputContext *ic = qLoadPlugin1<QPlatformInputContext, QPlatformInputContextPlugin> + QPlatformInputContext *ic = qLoadPlugin<QPlatformInputContext, QPlatformInputContextPlugin> (loader(), platform, paramList); if (ic && ic->isValid()) return ic; diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp index 14633d8b30..82cb4dd399 100644 --- a/src/gui/kernel/qplatformintegration.cpp +++ b/src/gui/kernel/qplatformintegration.cpp @@ -149,13 +149,11 @@ QPlatformServices *QPlatformIntegration::services() const /*! \fn QPlatformWindow *QPlatformIntegration::createPlatformWindow(QWindow *window) const - Factory function for QPlatformWindow. The \a window parameter is a pointer to the top level - window which the QPlatformWindow is supposed to be created for. + Factory function for QPlatformWindow. The \a window parameter is a pointer to the window + which the QPlatformWindow is supposed to be created for. - All top level windows have to have a QPlatformWindow, and it will be created when the - QPlatformWindow is set to be visible for the first time. If the top level window's flags are - changed, or if the top level window's QPlatformWindowFormat is changed, then the top level - window's QPlatformWindow is deleted and a new one is created. + All windows have to have a QPlatformWindow, and it will be created on-demand when the + QWindow is made visible for the first time, or explicitly through calling QWindow::create(). In the constructor, of the QPlatformWindow, the window flags, state, title and geometry of the \a window should be applied to the underlying window. If the resulting flags or state @@ -559,6 +557,17 @@ void QPlatformIntegration::sync() { } +/*! + \since 5.7 + + Should sound a bell, using the default volume and sound. + + \sa QApplication::beep() +*/ +void QPlatformIntegration::beep() const +{ +} + #ifndef QT_NO_OPENGL /*! Platform integration function for querying the OpenGL implementation type. diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h index af89a73455..382e16b4ca 100644 --- a/src/gui/kernel/qplatformintegration.h +++ b/src/gui/kernel/qplatformintegration.h @@ -176,6 +176,8 @@ public: void removeScreen(QScreen *screen); + virtual void beep() const; + protected: void screenAdded(QPlatformScreen *screen, bool isPrimary = false); void destroyScreen(QPlatformScreen *screen); diff --git a/src/gui/kernel/qplatformintegrationfactory.cpp b/src/gui/kernel/qplatformintegrationfactory.cpp index 5a1fb3ca83..2c8a7ce0f8 100644 --- a/src/gui/kernel/qplatformintegrationfactory.cpp +++ b/src/gui/kernel/qplatformintegrationfactory.cpp @@ -42,23 +42,12 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_LIBRARY Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)) + +#ifndef QT_NO_LIBRARY Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, (QPlatformIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) - -static inline QPlatformIntegration *loadIntegration(QFactoryLoader *loader, const QString &key, const QStringList ¶meters, int &argc, char ** argv) -{ - const int index = loader->indexOf(key); - if (index != -1) { - if (QPlatformIntegrationPlugin *factory = qobject_cast<QPlatformIntegrationPlugin *>(loader->instance(index))) - if (QPlatformIntegration *result = factory->create(key, parameters, argc, argv)) - return result; - } - return 0; -} - #endif // !QT_NO_LIBRARY QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platform, const QStringList ¶mList, int &argc, char **argv, const QString &platformPluginPath) @@ -67,19 +56,13 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString &platfor // Try loading the plugin from platformPluginPath first: if (!platformPluginPath.isEmpty()) { QCoreApplication::addLibraryPath(platformPluginPath); - if (QPlatformIntegration *ret = loadIntegration(directLoader(), platform, paramList, argc, argv)) + if (QPlatformIntegration *ret = qLoadPlugin<QPlatformIntegration, QPlatformIntegrationPlugin>(directLoader(), platform, paramList, argc, argv)) return ret; } - if (QPlatformIntegration *ret = loadIntegration(loader(), platform, paramList, argc, argv)) - return ret; #else - Q_UNUSED(platform); - Q_UNUSED(paramList); - Q_UNUSED(argc); - Q_UNUSED(argv); Q_UNUSED(platformPluginPath); #endif - return 0; + return qLoadPlugin<QPlatformIntegration, QPlatformIntegrationPlugin>(loader(), platform, paramList, argc, argv); } /*! diff --git a/src/gui/kernel/qplatformnativeinterface.cpp b/src/gui/kernel/qplatformnativeinterface.cpp index 8fa8debcb9..48e6091571 100644 --- a/src/gui/kernel/qplatformnativeinterface.cpp +++ b/src/gui/kernel/qplatformnativeinterface.cpp @@ -80,6 +80,15 @@ void * QPlatformNativeInterface::nativeResourceForBackingStore(const QByteArray return 0; } +#ifndef QT_NO_CURSOR +void *QPlatformNativeInterface::nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor) +{ + Q_UNUSED(resource); + Q_UNUSED(cursor); + return Q_NULLPTR; +} +#endif // !QT_NO_CURSOR + QPlatformNativeInterface::NativeResourceForIntegrationFunction QPlatformNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource) { Q_UNUSED(resource); diff --git a/src/gui/kernel/qplatformnativeinterface.h b/src/gui/kernel/qplatformnativeinterface.h index 71a4e9c768..c8d868a41d 100644 --- a/src/gui/kernel/qplatformnativeinterface.h +++ b/src/gui/kernel/qplatformnativeinterface.h @@ -65,6 +65,9 @@ public: virtual void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window); virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore); +#ifndef QT_NO_CURSOR + virtual void *nativeResourceForCursor(const QByteArray &resource, const QCursor &cursor); +#endif typedef void * (*NativeResourceForIntegrationFunction)(); typedef void * (*NativeResourceForContextFunction)(QOpenGLContext *context); diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index ce8548f628..61dacfa076 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -682,6 +682,41 @@ QString QPlatformTheme::defaultStandardButtonText(int button) return QString(); } +QString QPlatformTheme::removeMnemonics(const QString &original) +{ + QString returnText(original.size(), 0); + int finalDest = 0; + int currPos = 0; + int l = original.length(); + while (l) { + if (original.at(currPos) == QLatin1Char('&') + && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { + ++currPos; + --l; + if (l == 0) + break; + } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 && + original.at(currPos + 1) == QLatin1Char('&') && + original.at(currPos + 2) != QLatin1Char('&') && + original.at(currPos + 3) == QLatin1Char(')')) { + /* remove mnemonics its format is "\s*(&X)" */ + int n = 0; + while (finalDest > n && returnText.at(finalDest - n - 1).isSpace()) + ++n; + finalDest -= n; + currPos += 4; + l -= 4; + continue; + } + returnText[finalDest] = original.at(currPos); + ++currPos; + ++finalDest; + --l; + } + returnText.truncate(finalDest); + return returnText; +} + unsigned QPlatformThemePrivate::currentKeyPlatforms() { const uint keyboardScheme = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::KeyboardScheme).toInt(); diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h index 36fa7a65aa..71f5fea820 100644 --- a/src/gui/kernel/qplatformtheme.h +++ b/src/gui/kernel/qplatformtheme.h @@ -240,6 +240,7 @@ public: MediaSeekBackward, MediaVolume, MediaVolumeMuted, + LineEditClearButton, // do not add any values below/greater than this CustomBase = 0xf0000000 }; @@ -303,6 +304,7 @@ public: static QVariant defaultThemeHint(ThemeHint hint); static QString defaultStandardButtonText(int button); + static QString removeMnemonics(const QString &original); protected: explicit QPlatformTheme(QPlatformThemePrivate *priv); diff --git a/src/gui/kernel/qplatformthemefactory.cpp b/src/gui/kernel/qplatformthemefactory.cpp index bcc37dad06..a89e3088ea 100644 --- a/src/gui/kernel/qplatformthemefactory.cpp +++ b/src/gui/kernel/qplatformthemefactory.cpp @@ -51,23 +51,22 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, QPlatformTheme *QPlatformThemeFactory::create(const QString& key, const QString &platformPluginPath) { +#ifndef QT_NO_LIBRARY QStringList paramList = key.split(QLatin1Char(':')); const QString platform = paramList.takeFirst().toLower(); -#ifndef QT_NO_LIBRARY // Try loading the plugin from platformPluginPath first: if (!platformPluginPath.isEmpty()) { QCoreApplication::addLibraryPath(platformPluginPath); - if (QPlatformTheme *ret = qLoadPlugin1<QPlatformTheme, QPlatformThemePlugin>(directLoader(), platform, paramList)) + if (QPlatformTheme *ret = qLoadPlugin<QPlatformTheme, QPlatformThemePlugin>(directLoader(), platform, paramList)) return ret; } - if (QPlatformTheme *ret = qLoadPlugin1<QPlatformTheme, QPlatformThemePlugin>(loader(), platform, paramList)) - return ret; + return qLoadPlugin<QPlatformTheme, QPlatformThemePlugin>(loader(), platform, paramList); #else Q_UNUSED(key); Q_UNUSED(platformPluginPath); -#endif return 0; +#endif } /*! diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp index 9f38c9b78a..706786385b 100644 --- a/src/gui/kernel/qsimpledrag.cpp +++ b/src/gui/kernel/qsimpledrag.cpp @@ -191,6 +191,14 @@ Qt::DropAction QBasicDrag::drag(QDrag *o) return m_executed_drop_action; } +void QBasicDrag::cancelDrag() +{ + if (m_eventLoop) { + cancel(); + m_eventLoop->quit(); + } +} + void QBasicDrag::restoreCursor() { if (m_restoreCursor) { diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h index 055136c436..d5dacd8fd2 100644 --- a/src/gui/kernel/qsimpledrag_p.h +++ b/src/gui/kernel/qsimpledrag_p.h @@ -66,6 +66,7 @@ public: virtual ~QBasicDrag(); virtual Qt::DropAction drag(QDrag *drag) Q_DECL_OVERRIDE; + void cancelDrag() Q_DECL_OVERRIDE; virtual bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE; diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp index 7fc89112e6..eea26c05ed 100644 --- a/src/gui/kernel/qstylehints.cpp +++ b/src/gui/kernel/qstylehints.cpp @@ -65,6 +65,7 @@ class QStyleHintsPrivate : public QObjectPrivate public: inline QStyleHintsPrivate() : m_mouseDoubleClickInterval(-1) + , m_mousePressAndHoldInterval(-1) , m_startDragDistance(-1) , m_startDragTime(-1) , m_keyboardInputInterval(-1) @@ -72,6 +73,7 @@ public: {} int m_mouseDoubleClickInterval; + int m_mousePressAndHoldInterval; int m_startDragDistance; int m_startDragTime; int m_keyboardInputInterval; @@ -129,6 +131,21 @@ int QStyleHints::mouseDoubleClickInterval() const } /*! + Sets the \a mousePressAndHoldInterval. + \internal + \sa mousePressAndHoldInterval() + \since 5.7 +*/ +void QStyleHints::setMousePressAndHoldInterval(int mousePressAndHoldInterval) +{ + Q_D(QStyleHints); + if (d->m_mousePressAndHoldInterval == mousePressAndHoldInterval) + return; + d->m_mousePressAndHoldInterval = mousePressAndHoldInterval; + emit mousePressAndHoldIntervalChanged(mousePressAndHoldInterval); +} + +/*! \property QStyleHints::mousePressAndHoldInterval \brief the time limit in milliseconds that activates a press and hold. @@ -137,7 +154,10 @@ int QStyleHints::mouseDoubleClickInterval() const */ int QStyleHints::mousePressAndHoldInterval() const { - return themeableHint(QPlatformTheme::MousePressAndHoldInterval, QPlatformIntegration::MousePressAndHoldInterval).toInt(); + Q_D(const QStyleHints); + return d->m_mousePressAndHoldInterval >= 0 ? + d->m_mousePressAndHoldInterval : + themeableHint(QPlatformTheme::MousePressAndHoldInterval, QPlatformIntegration::MousePressAndHoldInterval).toInt(); } /*! diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h index c5b8241e07..7c46eaa746 100644 --- a/src/gui/kernel/qstylehints.h +++ b/src/gui/kernel/qstylehints.h @@ -51,7 +51,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject Q_PROPERTY(int keyboardAutoRepeatRate READ keyboardAutoRepeatRate STORED false CONSTANT FINAL) Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval NOTIFY keyboardInputIntervalChanged FINAL) Q_PROPERTY(int mouseDoubleClickInterval READ mouseDoubleClickInterval NOTIFY mouseDoubleClickIntervalChanged FINAL) - Q_PROPERTY(int mousePressAndHoldInterval READ mousePressAndHoldInterval STORED false CONSTANT FINAL) + Q_PROPERTY(int mousePressAndHoldInterval READ mousePressAndHoldInterval NOTIFY mousePressAndHoldIntervalChanged FINAL) Q_PROPERTY(QChar passwordMaskCharacter READ passwordMaskCharacter STORED false CONSTANT FINAL) Q_PROPERTY(int passwordMaskDelay READ passwordMaskDelay STORED false CONSTANT FINAL) Q_PROPERTY(bool setFocusOnTouchRelease READ setFocusOnTouchRelease STORED false CONSTANT FINAL) @@ -67,6 +67,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject public: void setMouseDoubleClickInterval(int mouseDoubleClickInterval); int mouseDoubleClickInterval() const; + void setMousePressAndHoldInterval(int mousePressAndHoldInterval); int mousePressAndHoldInterval() const; void setStartDragDistance(int startDragDistance); int startDragDistance() const; @@ -92,6 +93,7 @@ Q_SIGNALS: void cursorFlashTimeChanged(int cursorFlashTime); void keyboardInputIntervalChanged(int keyboardInputInterval); void mouseDoubleClickIntervalChanged(int mouseDoubleClickInterval); + void mousePressAndHoldIntervalChanged(int mousePressAndHoldInterval); void startDragDistanceChanged(int startDragDistance); void startDragTimeChanged(int startDragTime); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 21734f1619..45e0acec63 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -212,7 +212,7 @@ void QWindowPrivate::init() // If your application aborts here, you are probably creating a QWindow // before the screen list is populated. - if (!parentWindow && !topLevelScreen) { + if (Q_UNLIKELY(!parentWindow && !topLevelScreen)) { qFatal("Cannot create window: no screens available"); exit(1); } @@ -392,6 +392,9 @@ void QWindowPrivate::create(bool recursive) if (platformWindow) return; + if (q->parent()) + q->parent()->create(); + platformWindow = QGuiApplicationPrivate::platformIntegration()->createPlatformWindow(q); Q_ASSERT(platformWindow); @@ -403,13 +406,21 @@ void QWindowPrivate::create(bool recursive) QObjectList childObjects = q->children(); for (int i = 0; i < childObjects.size(); i ++) { QObject *object = childObjects.at(i); - if (object->isWindowType()) { - QWindow *window = static_cast<QWindow *>(object); - if (recursive) - window->d_func()->create(true); - if (window->d_func()->platformWindow) - window->d_func()->platformWindow->setParent(platformWindow); - } + if (!object->isWindowType()) + continue; + + QWindow *childWindow = static_cast<QWindow *>(object); + if (recursive) + childWindow->d_func()->create(recursive); + + // The child may have had deferred creation due to this window not being created + // at the time setVisible was called, so we re-apply the visible state, which + // may result in creating the child, and emitting the appropriate signals. + if (childWindow->isVisible()) + childWindow->setVisible(true); + + if (QPlatformWindow *childPlatformWindow = childWindow->d_func()->platformWindow) + childPlatformWindow->setParent(this->platformWindow); } QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated); @@ -474,14 +485,23 @@ void QWindow::setVisible(bool visible) { Q_D(QWindow); - if (d->visible == visible) + if (d->visible != visible) { + d->visible = visible; + emit visibleChanged(visible); + d->updateVisibility(); + } else if (d->platformWindow) { + // Visibility hasn't changed, and the platform window is in sync return; - d->visible = visible; - emit visibleChanged(visible); - d->updateVisibility(); + } - if (!d->platformWindow) - create(); + if (!d->platformWindow) { + // If we have a parent window, but the parent hasn't been created yet, we + // can defer creation until the parent is created or we're re-parented. + if (parent() && !parent()->handle()) + return; + else + create(); + } if (visible) { // remove posted quit events when showing a new window @@ -520,6 +540,7 @@ void QWindow::setVisible(bool visible) if (visible && (d->hasCursor || QGuiApplication::overrideCursor())) d->applyCursor(); #endif + d->platformWindow->setVisible(visible); if (!visible) { @@ -616,12 +637,17 @@ void QWindow::setParent(QWindow *parent) else d->connectToScreen(newScreen); + // If we were set visible, but not created because we were a child, and we're now + // re-parented into a created parent, or to being a top level, we need re-apply the + // visibility state, which will also create. + if (isVisible() && (!parent || parent->handle())) + setVisible(true); + if (d->platformWindow) { - if (parent && parent->d_func()->platformWindow) { - d->platformWindow->setParent(parent->d_func()->platformWindow); - } else { - d->platformWindow->setParent(0); - } + if (parent) + parent->create(); + + d->platformWindow->setParent(parent ? parent->d_func()->platformWindow : 0); } QGuiApplicationPrivate::updateBlockedStatus(this); @@ -1654,8 +1680,12 @@ void QWindow::destroy() QGuiApplicationPrivate::currentMouseWindow = parent(); if (QGuiApplicationPrivate::currentMousePressWindow == this) QGuiApplicationPrivate::currentMousePressWindow = parent(); - if (QGuiApplicationPrivate::tabletPressTarget == this) - QGuiApplicationPrivate::tabletPressTarget = parent(); + + for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) { + QGuiApplicationPrivate::TabletPointData &pointData = QGuiApplicationPrivate::tabletDevicePoints[i]; + if (pointData.target == this) + pointData.target = parent(); + } bool wasVisible = isVisible(); d->visibilityOnDestroy = wasVisible && d->platformWindow; diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp index 40f4ce94c2..7bdd3cb1bb 100644 --- a/src/gui/opengl/qopenglengineshadermanager.cpp +++ b/src/gui/opengl/qopenglengineshadermanager.cpp @@ -191,7 +191,7 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) #if defined(QT_DEBUG) // Check that all the elements have been filled: for (int i = 0; i < TotalSnippetCount; ++i) { - if (qShaderSnippets[i] == 0) { + if (Q_UNLIKELY(!qShaderSnippets[i])) { qFatal("Shader snippet for %s (#%d) is missing!", snippetNameStr(SnippetName(i)).constData(), i); } @@ -240,11 +240,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) simpleShaderProg->link(); - if (simpleShaderProg->isLinked()) { + if (Q_UNLIKELY(!simpleShaderProg->isLinked())) { + qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log())); + } else { if (!inCache) simpleShaderCache.store(simpleShaderProg, context); - } else { - qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log())); } // Compile the blit shader: @@ -281,11 +281,11 @@ QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context) } blitShaderProg->link(); - if (blitShaderProg->isLinked()) { + if (Q_UNLIKELY(!blitShaderProg->isLinked())) { + qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log())); + } else { if (!inCache) blitShaderCache.store(blitShaderProg, context); - } else { - qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log())); } #ifdef QT_GL_SHARED_SHADER_DEBUG diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index d614ad8401..bfd30735b2 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -5795,7 +5795,9 @@ QOpenGLES3Helper::QOpenGLES3Helper() { m_supportedVersion = qMakePair(2, 0); - if (init()) { + if (Q_UNLIKELY(!init())) { + qFatal("Failed to load libGLESv2"); + } else { const QPair<int, int> contextVersion = QOpenGLContext::currentContext()->format().version(); qCDebug(lcGLES3, "Resolving OpenGL ES 3.0 entry points"); @@ -5993,8 +5995,6 @@ QOpenGLES3Helper::QOpenGLES3Helper() } m_supportedVersion = qMakePair(3, 1); } - } else { - qFatal("Failed to load libGLESv2"); } } diff --git a/src/gui/opengl/qtriangulator_p.h b/src/gui/opengl/qtriangulator_p.h index 0ab3f7496c..4e13e5bdd0 100644 --- a/src/gui/opengl/qtriangulator_p.h +++ b/src/gui/opengl/qtriangulator_p.h @@ -88,12 +88,13 @@ public: inline QVertexIndexVector &operator = (const QVertexIndexVector &other) { - if (t == UnsignedInt) - indices32 = other.indices32; - else - indices16 = other.indices16; + if (t == UnsignedInt) + indices32 = other.indices32; + else + indices16 = other.indices16; - return *this; + t = other.t; + return *this; } private: diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 1e516e4581..283b6643b9 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -101,9 +101,10 @@ SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \ painting/qimagescale_sse4.cpp AVX2_SOURCES += painting/qdrawhelper_avx2.cpp -NEON_SOURCES += painting/qdrawhelper_neon.cpp +NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S +!ios:contains(QT_ARCH, "arm"): CONFIG+=no_clang_integrated_as !ios:!contains(QT_ARCH, "arm64"): DEFINES += ENABLE_PIXMAN_DRAWHELPERS MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 8c3fd2ce4f..3112d551b2 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -538,7 +538,7 @@ void QCosmeticStroker::drawPath(const QVectorPath &path) QPointF p2 = QPointF(p[-2], p[-1]) * state->matrix; calculateLastPoint(p1.x(), p1.y(), p2.x(), p2.y()); } - int caps = (!closed & drawCaps) ? CapBegin : NoCaps; + int caps = (!closed && drawCaps) ? CapBegin : NoCaps; // qDebug() << "closed =" << closed << capString(caps); points += 2; @@ -589,7 +589,7 @@ void QCosmeticStroker::drawPath(const QVectorPath &path) const qreal *end = points + 2*path.elementCount(); // handle closed path case bool closed = path.hasImplicitClose() || (points[0] == end[-2] && points[1] == end[-1]); - int caps = (!closed & drawCaps) ? CapBegin : NoCaps; + int caps = (!closed && drawCaps) ? CapBegin : NoCaps; if (closed) { QPointF p2 = QPointF(end[-2], end[-1]) * state->matrix; calculateLastPoint(p2.x(), p2.y(), p.x(), p.y()); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 87ceb9a89d..e7b81ebdd3 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -2337,8 +2337,8 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c uint bl = s2[x1]; uint br = s2[x2]; -#if defined(__SSE2__) - // The SSE2 optimized interpolate_4_pixels is faster than interpolate_4_pixels_16. +#if defined(__SSE2__) || defined(__ARM_NEON__) + // The optimized interpolate_4_pixels are faster than interpolate_4_pixels_16. int distx = (fx & 0x0000ffff) >> 8; int disty = (fy & 0x0000ffff) >> 8; *b = interpolate_4_pixels(tl, tr, bl, br, distx, disty); @@ -2567,12 +2567,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper if ((fdx < 0 && fdx > -(fixed_scale / 8)) || std::abs(data->m22) < (1./8.)) { // scale up more than 8x int disty = (fy & 0x0000ffff) >> 8; for (int i = 0; i < len; ++i) { - uint tl = buf1[i * 2 + 0]; - uint tr = buf1[i * 2 + 1]; - uint bl = buf2[i * 2 + 0]; - uint br = buf2[i * 2 + 1]; int distx = (fracX & 0x0000ffff) >> 8; - b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty); + b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty); fracX += fdx; } } else { //scale down @@ -2633,15 +2629,10 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper if (std::abs(data->m11) > 8 || std::abs(data->m22) > 8) { //if we are zooming more than 8 times, we use 8bit precision for the position. for (int i = 0; i < len; ++i) { - uint tl = buf1[i * 2 + 0]; - uint tr = buf1[i * 2 + 1]; - uint bl = buf2[i * 2 + 0]; - uint br = buf2[i * 2 + 1]; - int distx = (fracX & 0x0000ffff) >> 8; int disty = (fracY & 0x0000ffff) >> 8; - b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty); + b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty); fracX += fdx; fracY += fdy; } @@ -2731,12 +2722,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper int distx = distxs[i]; int disty = distys[i]; - uint tl = buf1[i * 2 + 0]; - uint tr = buf1[i * 2 + 1]; - uint bl = buf2[i * 2 + 0]; - uint br = buf2[i * 2 + 1]; - - b[i] = interpolate_4_pixels(tl, tr, bl, br, distx, disty); + b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty); } length -= len; b += len; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 1ff19f4e04..fc24e22cac 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -629,31 +629,75 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { } #endif -#ifdef __SSE2__ +#if defined(__SSE2__) +static Q_ALWAYS_INLINE uint interpolate_4_pixels_sse2(__m128i vt, __m128i vb, uint distx, uint disty) +{ + // First interpolate top and bottom pixels in parallel. + vt = _mm_unpacklo_epi8(vt, _mm_setzero_si128()); + vb = _mm_unpacklo_epi8(vb, _mm_setzero_si128()); + vt = _mm_mullo_epi16(vt, _mm_set1_epi16(256 - disty)); + vb = _mm_mullo_epi16(vb, _mm_set1_epi16(disty)); + __m128i vlr = _mm_add_epi16(vt, vb); + vlr = _mm_srli_epi16(vlr, 8); + // vlr now contains the result of the first two interpolate calls vlr = unpacked((xright << 64) | xleft) + + // Now the last interpolate between left and right.. + const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - distx), _MM_SHUFFLE(0, 0, 0, 0)); + const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0)); + const __m128i vmulx = _mm_unpacklo_epi16(vidistx, vdistx); + vlr = _mm_unpacklo_epi16(vlr, _mm_srli_si128(vlr, 8)); + // vlr now contains the colors of left and right interleaved { la, ra, lr, rr, lg, rg, lb, rb } + vlr = _mm_madd_epi16(vlr, vmulx); // Multiply and horizontal add. + vlr = _mm_srli_epi32(vlr, 8); + vlr = _mm_packs_epi32(vlr, vlr); + vlr = _mm_packus_epi16(vlr, vlr); + return _mm_cvtsi128_si32(vlr); +} + +static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty) +{ + __m128i vt = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(tr)); + __m128i vb = _mm_unpacklo_epi32(_mm_cvtsi32_si128(bl), _mm_cvtsi32_si128(br)); + return interpolate_4_pixels_sse2(vt, vb, distx, disty); +} + +static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint distx, uint disty) +{ + __m128i vt = _mm_loadl_epi64((const __m128i*)t); + __m128i vb = _mm_loadl_epi64((const __m128i*)b); + return interpolate_4_pixels_sse2(vt, vb, distx, disty); +} +#elif defined(__ARM_NEON__) +static Q_ALWAYS_INLINE uint interpolate_4_pixels_neon(uint32x2_t vt32, uint32x2_t vb32, uint distx, uint disty) +{ + uint16x8_t vt16 = vmovl_u8(vreinterpret_u8_u32(vt32)); + uint16x8_t vb16 = vmovl_u8(vreinterpret_u8_u32(vb32)); + vt16 = vmulq_n_u16(vt16, 256 - disty); + vt16 = vmlaq_n_u16(vt16, vb16, disty); + vt16 = vshrq_n_u16(vt16, 8); + uint16x4_t vl16 = vget_low_u16(vt16); + uint16x4_t vr16 = vget_high_u16(vt16); + vl16 = vmul_n_u16(vl16, 256 - distx); + vl16 = vmla_n_u16(vl16, vr16, distx); + vl16 = vshr_n_u16(vl16, 8); + uint8x8_t vr = vmovn_u16(vcombine_u16(vl16, vl16)); + return vget_lane_u32(vreinterpret_u32_u8(vr), 0); +} + static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty) { - // First interpolate right and left pixels in parallel. - __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl)); - __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br)); - vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128()); - vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128()); - vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx)); - vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx)); - __m128i vtb = _mm_add_epi16(vl, vr); - vtb = _mm_srli_epi16(vtb, 8); - // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop) - - // Now the last interpolate between top and bottom interpolations. - const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0)); - const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0)); - const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty); - vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8)); - // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb } - vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add. - vtb = _mm_srli_epi32(vtb, 8); - vtb = _mm_packs_epi32(vtb, _mm_setzero_si128()); - vtb = _mm_packus_epi16(vtb, _mm_setzero_si128()); - return _mm_cvtsi128_si32(vtb); + uint32x2_t vt32 = vmov_n_u32(tl); + uint32x2_t vb32 = vmov_n_u32(bl); + vt32 = vset_lane_u32(tr, vt32, 1); + vb32 = vset_lane_u32(br, vb32, 1); + return interpolate_4_pixels_neon(vt32, vb32, distx, disty); +} + +static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint distx, uint disty) +{ + uint32x2_t vt32 = vld1_u32(t); + uint32x2_t vb32 = vld1_u32(b); + return interpolate_4_pixels_neon(vt32, vb32, distx, disty); } #else static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty) @@ -664,6 +708,11 @@ static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); } + +static inline uint interpolate_4_pixels(const uint t[], const uint b[], uint distx, uint disty) +{ + return interpolate_4_pixels(t[0], t[1], b[0], b[1], distx, disty); +} #endif #if Q_BYTE_ORDER == Q_BIG_ENDIAN diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp index 33dccc5374..9381afa8e7 100644 --- a/src/gui/painting/qimagescale.cpp +++ b/src/gui/painting/qimagescale.cpp @@ -277,6 +277,18 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow); #endif +#if defined(__ARM_NEON__) +template<bool RGB> +void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); +template<bool RGB> +void qt_qimageScaleAARGBA_down_x_up_y_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); +template<bool RGB> +void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); +#endif + static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, int dw, int dh, int dow, int sow) { @@ -296,7 +308,7 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest, const unsigned int *pix = sptr + xpoints[x]; const int xap = xapoints[x]; if (xap > 0) - *dptr = interpolate_4_pixels(pix[0], pix[1], pix[sow], pix[sow + 1], xap, yap); + *dptr = interpolate_4_pixels(pix, pix + sow, xap, yap); else *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap); dptr++; @@ -329,6 +341,10 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_up_x_down_y_neon<false>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dw, dh, dow, sow); } @@ -338,6 +354,10 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_down_x_up_y_neon<false>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dw, dh, dow, sow); } @@ -347,6 +367,10 @@ static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_down_xy_neon<false>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGBA_down_xy(isi, dest, dw, dh, dow, sow); } @@ -522,6 +546,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_up_x_down_y_neon<true>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGB_up_x_down_y(isi, dest, dw, dh, dow, sow); } @@ -531,6 +559,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_down_x_up_y_neon<true>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGB_down_x_up_y(isi, dest, dw, dh, dow, sow); } @@ -540,6 +572,10 @@ static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest, if (qCpuHasFeature(SSE4_1)) qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dw, dh, dow, sow); else +#elif defined(__ARM_NEON__) + if (qCpuHasFeature(NEON)) + qt_qimageScaleAARGBA_down_xy_neon<true>(isi, dest, dw, dh, dow, sow); + else #endif qt_qimageScaleAARGB_down_xy(isi, dest, dw, dh, dow, sow); } diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp new file mode 100644 index 0000000000..88389bebb9 --- /dev/null +++ b/src/gui/painting/qimagescale_neon.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qimagescale_p.h" +#include "qimage.h" +#include <private/qsimd_p.h> + +#if defined(__ARM_NEON__) + +QT_BEGIN_NAMESPACE + +using namespace QImageScale; + +inline static uint32x4_t qt_qimageScaleAARGBA_helper(const unsigned int *pix, int xyap, int Cxy, int step) +{ + uint32x2_t vpix32 = vmov_n_u32(*pix); + uint16x4_t vpix16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vpix32))); + uint32x4_t vx = vmull_n_u16(vpix16, xyap); + int i; + for (i = (1 << 14) - xyap; i > Cxy; i -= Cxy) { + pix += step; + vpix32 = vmov_n_u32(*pix); + vpix16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vpix32))); + vx = vaddq_u32(vx, vmull_n_u16(vpix16, Cxy)); + } + pix += step; + vpix32 = vmov_n_u32(*pix); + vpix16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(vpix32))); + vx = vaddq_u32(vx, vmull_n_u16(vpix16, i)); + return vx; +} + +template<bool RGB> +void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow) +{ + const unsigned int **ypoints = isi->ypoints; + int *xpoints = isi->xpoints; + int *xapoints = isi->xapoints; + int *yapoints = isi->yapoints; + + /* go through every scanline in the output buffer */ + for (int y = 0; y < dh; y++) { + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; + + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + const unsigned int *sptr = ypoints[y] + xpoints[x]; + uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow); + + int xap = xapoints[x]; + if (xap > 0) { + uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow); + + vx = vmulq_n_u32(vx, 256 - xap); + vr = vmulq_n_u32(vr, xap); + vx = vaddq_u32(vx, vr); + vx = vshrq_n_u32(vx, 8); + } + vx = vshrq_n_u32(vx, 14); + const uint16x4_t vx16 = vmovn_u32(vx); + const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16)); + *dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0); + if (RGB) + *dptr |= 0xff000000; + dptr++; + } + } +} + +template<bool RGB> +void qt_qimageScaleAARGBA_down_x_up_y_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow) +{ + const unsigned int **ypoints = isi->ypoints; + int *xpoints = isi->xpoints; + int *xapoints = isi->xapoints; + int *yapoints = isi->yapoints; + + /* go through every scanline in the output buffer */ + for (int y = 0; y < dh; y++) { + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + int Cx = xapoints[x] >> 16; + int xap = xapoints[x] & 0xffff; + + const unsigned int *sptr = ypoints[y] + xpoints[x]; + uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); + + int yap = yapoints[y]; + if (yap > 0) { + uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1); + + vx = vmulq_n_u32(vx, 256 - yap); + vr = vmulq_n_u32(vr, yap); + vx = vaddq_u32(vx, vr); + vx = vshrq_n_u32(vx, 8); + } + vx = vshrq_n_u32(vx, 14); + const uint16x4_t vx16 = vmovn_u32(vx); + const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16)); + *dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0); + if (RGB) + *dptr |= 0xff000000; + dptr++; + } + } +} + +template<bool RGB> +void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow) +{ + const unsigned int **ypoints = isi->ypoints; + int *xpoints = isi->xpoints; + int *xapoints = isi->xapoints; + int *yapoints = isi->yapoints; + + for (int y = 0; y < dh; y++) { + int Cy = yapoints[y] >> 16; + int yap = yapoints[y] & 0xffff; + + unsigned int *dptr = dest + (y * dow); + for (int x = 0; x < dw; x++) { + const int Cx = xapoints[x] >> 16; + const int xap = xapoints[x] & 0xffff; + + const unsigned int *sptr = ypoints[y] + xpoints[x]; + uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); + vx = vshrq_n_u32(vx, 4); + uint32x4_t vr = vmulq_n_u32(vx, yap); + + int j; + for (j = (1 << 14) - yap; j > Cy; j -= Cy) { + sptr += sow; + vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); + vx = vshrq_n_u32(vx, 4); + vx = vmulq_n_u32(vx, Cy); + vr = vaddq_u32(vr, vx); + } + sptr += sow; + vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); + vx = vshrq_n_u32(vx, 4); + vx = vmulq_n_u32(vx, j); + vr = vaddq_u32(vr, vx); + + vx = vshrq_n_u32(vr, 24); + const uint16x4_t vx16 = vmovn_u32(vx); + const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16)); + *dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0); + if (RGB) + *dptr |= 0xff000000; + dptr++; + } + } +} + +template void qt_qimageScaleAARGBA_up_x_down_y_neon<false>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +template void qt_qimageScaleAARGBA_up_x_down_y_neon<true>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +template void qt_qimageScaleAARGBA_down_x_up_y_neon<false>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +template void qt_qimageScaleAARGBA_down_x_up_y_neon<true>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +template void qt_qimageScaleAARGBA_down_xy_neon<false>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +template void qt_qimageScaleAARGBA_down_xy_neon<true>(QImageScaleInfo *isi, unsigned int *dest, + int dw, int dh, int dow, int sow); + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp index a2bab58922..aa4a609d6c 100644 --- a/src/gui/painting/qpaintengine_blitter.cpp +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -190,7 +190,7 @@ private: } void setSourcePixmapMask() { - updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true); + updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, false); updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false); updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true); @@ -212,7 +212,7 @@ private: void setSourceOverScaledPixmapMask() { setSourceOverPixmapMask(); - updateStateBits(&drawRectMask, STATE_XFORM_SCALE, true); + updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true); } void setOpacityPixmapMask() { diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h index ab44851ec7..17a648176c 100644 --- a/src/gui/painting/qpaintengine_blitter_p.h +++ b/src/gui/painting/qpaintengine_blitter_p.h @@ -60,46 +60,48 @@ class Q_GUI_EXPORT QBlitterPaintEngine : public QRasterPaintEngine public: QBlitterPaintEngine(QBlittablePlatformPixmap *p); - virtual QPaintEngine::Type type() const { return Blitter; } + virtual QPaintEngine::Type type() const Q_DECL_OVERRIDE + { return Blitter; } - virtual bool begin(QPaintDevice *pdev); - virtual bool end(); + virtual bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE; + virtual bool end() Q_DECL_OVERRIDE; // Call down into QBlittable - virtual void fill(const QVectorPath &path, const QBrush &brush); - virtual void fillRect(const QRectF &rect, const QBrush &brush); - virtual void fillRect(const QRectF &rect, const QColor &color); - virtual void drawRects(const QRect *rects, int rectCount); - virtual void drawRects(const QRectF *rects, int rectCount); - void drawPixmap(const QPointF &p, const QPixmap &pm); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE; + void fillRect(const QRectF &rect, const QBrush &brush) Q_DECL_OVERRIDE; + void fillRect(const QRectF &rect, const QColor &color) Q_DECL_OVERRIDE; + void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE; + void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE; + void drawPixmap(const QPointF &p, const QPixmap &pm) Q_DECL_OVERRIDE; + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE; // State tracking - void setState(QPainterState *s); - virtual void clipEnabledChanged(); - virtual void penChanged(); - virtual void brushChanged(); - virtual void opacityChanged(); - virtual void compositionModeChanged(); - virtual void renderHintsChanged(); - virtual void transformChanged(); + void setState(QPainterState *s) Q_DECL_OVERRIDE; + virtual void clipEnabledChanged() Q_DECL_OVERRIDE; + virtual void penChanged() Q_DECL_OVERRIDE; + virtual void brushChanged() Q_DECL_OVERRIDE; + virtual void opacityChanged() Q_DECL_OVERRIDE; + virtual void compositionModeChanged() Q_DECL_OVERRIDE; + virtual void renderHintsChanged() Q_DECL_OVERRIDE; + virtual void transformChanged() Q_DECL_OVERRIDE; // Override to lock the QBlittable before using raster - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - void fillPath(const QPainterPath &path, QSpanData *fillData); - void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawEllipse(const QRectF &rect); - void drawImage(const QPointF &p, const QImage &img); + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; + void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; + void fillPath(const QPainterPath &path, QSpanData *fillData) Q_DECL_OVERRIDE; + void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; + void drawEllipse(const QRectF &rect) Q_DECL_OVERRIDE; + void drawImage(const QPointF &p, const QImage &img) Q_DECL_OVERRIDE; void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - void drawTextItem(const QPointF &p, const QTextItem &textItem); - void drawPoints(const QPointF *points, int pointCount); - void drawPoints(const QPoint *points, int pointCount); - void stroke(const QVectorPath &path, const QPen &pen); - void drawStaticTextItem(QStaticTextItem *); - bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine); + Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE; + void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr) Q_DECL_OVERRIDE; + void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE; + void drawPoints(const QPointF *points, int pointCount) Q_DECL_OVERRIDE; + void drawPoints(const QPoint *points, int pointCount) Q_DECL_OVERRIDE; + void stroke(const QVectorPath &path, const QPen &pen) Q_DECL_OVERRIDE; + void drawStaticTextItem(QStaticTextItem *) Q_DECL_OVERRIDE; + bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, + QFontEngine *fontEngine) Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index d71297bd60..651149c4c6 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1338,9 +1338,9 @@ void QRasterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) */ -/*! - \internal -*/ +///*! +// \internal +//*/ void QRasterPaintEngine::fillPath(const QPainterPath &path, QSpanData *fillData) { #ifdef QT_DEBUG_DRAW diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 4e6e0b2f73..7ac1630692 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -128,20 +128,20 @@ public: QRasterPaintEngine(QPaintDevice *device); ~QRasterPaintEngine(); - bool begin(QPaintDevice *device); - bool end(); - - void penChanged(); - void brushChanged(); - void brushOriginChanged(); - void opacityChanged(); - void compositionModeChanged(); - void renderHintsChanged(); - void transformChanged(); - void clipEnabledChanged(); - - void setState(QPainterState *s); - QPainterState *createState(QPainterState *orig) const; + bool begin(QPaintDevice *device) Q_DECL_OVERRIDE; + bool end() Q_DECL_OVERRIDE; + + void penChanged() Q_DECL_OVERRIDE; + void brushChanged() Q_DECL_OVERRIDE; + void brushOriginChanged() Q_DECL_OVERRIDE; + void opacityChanged() Q_DECL_OVERRIDE; + void compositionModeChanged() Q_DECL_OVERRIDE; + void renderHintsChanged() Q_DECL_OVERRIDE; + void transformChanged() Q_DECL_OVERRIDE; + void clipEnabledChanged() Q_DECL_OVERRIDE; + + void setState(QPainterState *s) Q_DECL_OVERRIDE; + QPainterState *createState(QPainterState *orig) const Q_DECL_OVERRIDE; inline QRasterPaintEngineState *state() { return static_cast<QRasterPaintEngineState *>(QPaintEngineEx::state()); } @@ -154,42 +154,43 @@ public: void updateMatrix(const QTransform &matrix); - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - void fillPath(const QPainterPath &path, QSpanData *fillData); - void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + virtual void fillPath(const QPainterPath &path, QSpanData *fillData); + virtual void fillPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawEllipse(const QRectF &rect); + void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; + void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE; - void fillRect(const QRectF &rect, const QBrush &brush); - void fillRect(const QRectF &rect, const QColor &color); + void drawEllipse(const QRectF &rect) Q_DECL_OVERRIDE; - void drawRects(const QRect *rects, int rectCount); - void drawRects(const QRectF *rects, int rectCount); + void fillRect(const QRectF &rect, const QBrush &brush) Q_DECL_OVERRIDE; + void fillRect(const QRectF &rect, const QColor &color) Q_DECL_OVERRIDE; - void drawPixmap(const QPointF &p, const QPixmap &pm); - void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - void drawImage(const QPointF &p, const QImage &img); + void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE; + void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE; + + void drawPixmap(const QPointF &p, const QPixmap &pm) Q_DECL_OVERRIDE; + void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE; + void drawImage(const QPointF &p, const QImage &img) Q_DECL_OVERRIDE; void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags flags = Qt::AutoColor); - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - void drawTextItem(const QPointF &p, const QTextItem &textItem); + Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE; + void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr) Q_DECL_OVERRIDE; + void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE; - void drawLines(const QLine *line, int lineCount); - void drawLines(const QLineF *line, int lineCount); + void drawLines(const QLine *line, int lineCount) Q_DECL_OVERRIDE; + void drawLines(const QLineF *line, int lineCount) Q_DECL_OVERRIDE; - void drawPoints(const QPointF *points, int pointCount); - void drawPoints(const QPoint *points, int pointCount); + void drawPoints(const QPointF *points, int pointCount) Q_DECL_OVERRIDE; + void drawPoints(const QPoint *points, int pointCount) Q_DECL_OVERRIDE; - void stroke(const QVectorPath &path, const QPen &pen); - void fill(const QVectorPath &path, const QBrush &brush); + void stroke(const QVectorPath &path, const QPen &pen) Q_DECL_OVERRIDE; + void fill(const QVectorPath &path, const QBrush &brush) Q_DECL_OVERRIDE; - void clip(const QVectorPath &path, Qt::ClipOperation op); - void clip(const QRect &rect, Qt::ClipOperation op); - void clip(const QRegion ®ion, Qt::ClipOperation op); + void clip(const QVectorPath &path, Qt::ClipOperation op) Q_DECL_OVERRIDE; + void clip(const QRect &rect, Qt::ClipOperation op) Q_DECL_OVERRIDE; + void clip(const QRegion ®ion, Qt::ClipOperation op) Q_DECL_OVERRIDE; inline const QClipData *clipData() const; - void drawStaticTextItem(QStaticTextItem *textItem); + void drawStaticTextItem(QStaticTextItem *textItem) Q_DECL_OVERRIDE; virtual bool drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, QFontEngine *fontEngine); @@ -219,12 +220,12 @@ public: QRasterBuffer *rasterBuffer(); void alphaPenBlt(const void* src, int bpl, int depth, int rx,int ry,int w,int h); - Type type() const { return Raster; } + Type type() const Q_DECL_OVERRIDE { return Raster; } - QPoint coordinateOffset() const; + QPoint coordinateOffset() const Q_DECL_OVERRIDE; - bool requiresPretransformedGlyphPositions(QFontEngine *fontEngine, const QTransform &m) const; - bool shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const; + bool requiresPretransformedGlyphPositions(QFontEngine *fontEngine, const QTransform &m) const Q_DECL_OVERRIDE; + bool shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &m) const Q_DECL_OVERRIDE; protected: QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *); diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 48010c0a71..558ab81847 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1856,6 +1856,8 @@ bool QPainterPath::contains(const QPointF &pt) const : ((winding_number % 2) != 0)); } +enum PainterDirections { Left, Right, Top, Bottom }; + static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y2, const QRectF &rect) { @@ -1864,7 +1866,6 @@ static bool qt_painterpath_isect_line_rect(qreal x1, qreal y1, qreal x2, qreal y qreal top = rect.top(); qreal bottom = rect.bottom(); - enum { Left, Right, Top, Bottom }; // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html int p1 = ((x1 < left) << Left) | ((x1 > right) << Right) diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index fab9506ff2..51b37b2ef4 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -44,7 +44,7 @@ class QRgba64 { // Make sure that the representation always has the order: red green blue alpha, independent // of byte order. This way, vector operations that assume 4 16-bit values see the correct ones. - enum { + enum Shifts { #if Q_BYTE_ORDER == Q_BIG_ENDIAN RedShift = 48, GreenShift = 32, diff --git a/src/gui/text/qabstracttextdocumentlayout.cpp b/src/gui/text/qabstracttextdocumentlayout.cpp index 7735fd6b46..ea6c5d1984 100644 --- a/src/gui/text/qabstracttextdocumentlayout.cpp +++ b/src/gui/text/qabstracttextdocumentlayout.cpp @@ -447,8 +447,8 @@ void QAbstractTextDocumentLayout::unregisterHandler(int objectType, QObject *com { Q_D(QAbstractTextDocumentLayout); - HandlerHash::iterator it = d->handlers.find(objectType); - if (it != d->handlers.end() && (!component || component == it->component)) { + const auto it = d->handlers.constFind(objectType); + if (it != d->handlers.cend() && (!component || component == it->component)) { if (component) disconnect(component, SIGNAL(destroyed(QObject*)), this, SLOT(_q_handlerDestroyed(QObject*))); d->handlers.erase(it); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 947c538234..ed4a932a32 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -549,7 +549,7 @@ QFont::QFont(const QFont &font, QPaintDevice *pd) d->dpi = dpi; d->screen = screen; } else { - d = font.d.data(); + d = font.d; } } @@ -654,7 +654,7 @@ QFont::QFont(const QString &family, int pointSize, int weight, bool italic) Constructs a font that is a copy of \a font. */ QFont::QFont(const QFont &font) - : d(font.d.data()), resolve_mask(font.resolve_mask) + : d(font.d), resolve_mask(font.resolve_mask) { } @@ -670,7 +670,7 @@ QFont::~QFont() */ QFont &QFont::operator=(const QFont &font) { - d = font.d.data(); + d = font.d; resolve_mask = font.resolve_mask; return *this; } @@ -1647,8 +1647,8 @@ bool QFont::operator<(const QFont &f) const { if (f.d == d) return false; // the < operator for fontdefs ignores point sizes. - QFontDef &r1 = f.d->request; - QFontDef &r2 = d->request; + const QFontDef &r1 = f.d->request; + const QFontDef &r2 = d->request; if (r1.pointSize != r2.pointSize) return r1.pointSize < r2.pointSize; if (r1.pixelSize != r2.pixelSize) return r1.pixelSize < r2.pixelSize; if (r1.weight != r2.weight) return r1.weight < r2.weight; @@ -2388,7 +2388,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font) that is not screen-compatible. */ QFontInfo::QFontInfo(const QFont &font) - : d(font.d.data()) + : d(font.d) { } @@ -2396,7 +2396,7 @@ QFontInfo::QFontInfo(const QFont &font) Constructs a copy of \a fi. */ QFontInfo::QFontInfo(const QFontInfo &fi) - : d(fi.d.data()) + : d(fi.d) { } @@ -2412,7 +2412,7 @@ QFontInfo::~QFontInfo() */ QFontInfo &QFontInfo::operator=(const QFontInfo &fi) { - d = fi.d.data(); + d = fi.d; return *this; } diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 1b9852c20c..2f8af2315d 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -1388,7 +1388,7 @@ QString QFontDatabase::styleString(const QFontInfo &fontInfo) */ QFontDatabase::QFontDatabase() { - if (!qApp || !QGuiApplicationPrivate::platformIntegration()) + if (Q_UNLIKELY(!qApp || !QGuiApplicationPrivate::platformIntegration())) qFatal("QFontDatabase: Must construct a QGuiApplication before accessing QFontDatabase"); QMutexLocker locker(fontDatabaseMutex()); diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp index 5bc9fe3c7f..0fc7fc9242 100644 --- a/src/gui/text/qfontmetrics.cpp +++ b/src/gui/text/qfontmetrics.cpp @@ -145,7 +145,7 @@ extern void qt_format_text(const QFont& font, const QRectF &_r, metrics that are compatible with a certain paint device. */ QFontMetrics::QFontMetrics(const QFont &font) - : d(font.d.data()) + : d(font.d) { } @@ -171,7 +171,7 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice) d->dpi = dpi; d->screen = screen; } else { - d = font.d.data(); + d = font.d; } } @@ -180,7 +180,7 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice) Constructs a copy of \a fm. */ QFontMetrics::QFontMetrics(const QFontMetrics &fm) - : d(fm.d.data()) + : d(fm.d) { } @@ -197,7 +197,7 @@ QFontMetrics::~QFontMetrics() */ QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm) { - d = fm.d.data(); + d = fm.d; return *this; } @@ -995,7 +995,7 @@ int QFontMetrics::lineWidth() const from the given \a fontMetrics object. */ QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics) - : d(fontMetrics.d.data()) + : d(fontMetrics.d) { } @@ -1006,7 +1006,7 @@ QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics) */ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other) { - d = other.d.data(); + d = other.d; return *this; } @@ -1034,7 +1034,7 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other) metrics that are compatible with a certain paint device. */ QFontMetricsF::QFontMetricsF(const QFont &font) - : d(font.d.data()) + : d(font.d) { } @@ -1060,7 +1060,7 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice) d->dpi = dpi; d->screen = screen; } else { - d = font.d.data(); + d = font.d; } } @@ -1069,7 +1069,7 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice) Constructs a copy of \a fm. */ QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm) - : d(fm.d.data()) + : d(fm.d) { } @@ -1086,7 +1086,7 @@ QFontMetricsF::~QFontMetricsF() */ QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm) { - d = fm.d.data(); + d = fm.d; return *this; } diff --git a/src/gui/text/qplatformfontdatabase.cpp b/src/gui/text/qplatformfontdatabase.cpp index 0695c2eff4..113e1d89d4 100644 --- a/src/gui/text/qplatformfontdatabase.cpp +++ b/src/gui/text/qplatformfontdatabase.cpp @@ -511,7 +511,7 @@ static const quint8 requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { 14, 127 }, // Nko }; -enum { +enum CsbBits { Latin1CsbBit = 0, CentralEuropeCsbBit = 1, TurkishCsbBit = 4, diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp index 0fd5f510c7..b74ce23631 100644 --- a/src/gui/text/qrawfont.cpp +++ b/src/gui/text/qrawfont.cpp @@ -44,6 +44,7 @@ #include <qpa/qplatformfontdatabase.h> #include <QtCore/qendian.h> +#include <QtCore/qfile.h> QT_BEGIN_NAMESPACE @@ -687,7 +688,7 @@ extern int qt_script_for_writing_system(QFontDatabase::WritingSystem writingSyst QRawFont QRawFont::fromFont(const QFont &font, QFontDatabase::WritingSystem writingSystem) { QRawFont rawFont; - QFontPrivate *font_d = QFontPrivate::get(font); + const QFontPrivate *font_d = QFontPrivate::get(font); int script = qt_script_for_writing_system(writingSystem); QFontEngine *fe = font_d->engineForScript(script); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 1c924175e2..2f755d0c25 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1548,7 +1548,7 @@ void QTextEngine::validate() const if (block.docHandle()) { layoutData->string = block.text(); if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) - layoutData->string += QLatin1Char(block.next().isValid() ? 0xb6 : 0x20); + layoutData->string += QLatin1Char(block.next().isValid() ? 0xb6 : 0xA7); } else { layoutData->string = text; } diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index f8f41bb53d..a09ed2c040 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -1140,6 +1140,7 @@ void QTextHtmlParserNode::setListStyle(const QVector<QCss::Value> &cssValues) for (int i = 0; i < cssValues.count(); ++i) { if (cssValues.at(i).type == QCss::Value::KnownIdentifier) { switch (static_cast<QCss::KnownValue>(cssValues.at(i).variant.toInt())) { + case QCss::Value_None: hasOwnListStyle = true; listStyle = QTextListFormat::ListStyleUndefined; break; case QCss::Value_Disc: hasOwnListStyle = true; listStyle = QTextListFormat::ListDisc; break; case QCss::Value_Square: hasOwnListStyle = true; listStyle = QTextListFormat::ListSquare; break; case QCss::Value_Circle: hasOwnListStyle = true; listStyle = QTextListFormat::ListCircle; break; @@ -1495,6 +1496,8 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes) node->listStyle = QTextListFormat::ListDisc; else if (value == QLatin1String("circle")) node->listStyle = QTextListFormat::ListCircle; + else if (value == QLatin1String("none")) + node->listStyle = QTextListFormat::ListStyleUndefined; } } break; diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp index 16d81a7d6d..d7a418e7c8 100644 --- a/src/gui/text/qtextimagehandler.cpp +++ b/src/gui/text/qtextimagehandler.cpp @@ -38,6 +38,7 @@ #include <qtextformat.h> #include <qpainter.h> #include <qdebug.h> +#include <qfile.h> #include <private/qtextengine_p.h> #include <qpalette.h> #include <qthread.h> diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp index df7c8b9c71..6552309dcb 100644 --- a/src/gui/text/qtextobject.cpp +++ b/src/gui/text/qtextobject.cpp @@ -663,6 +663,8 @@ QTextFrame::iterator::iterator(QTextFrame *frame, int block, int begin, int end) cb = block; } +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + /*! Copy constructor. Constructs a copy of the \a other iterator. */ @@ -689,6 +691,8 @@ QTextFrame::iterator &QTextFrame::iterator::operator=(const iterator &other) return *this; } +#endif + /*! Returns the current frame pointed to by the iterator, or 0 if the iterator currently points to a block. diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h index fbb90e42b0..29eeddc414 100644 --- a/src/gui/text/qtextobject.h +++ b/src/gui/text/qtextobject.h @@ -143,8 +143,10 @@ public: iterator(QTextFrame *frame, int block, int begin, int end); public: iterator(); +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) iterator(const iterator &o); iterator &operator=(const iterator &o); +#endif QTextFrame *parentFrame() const { return f; } @@ -248,7 +250,9 @@ public: iterator(const QTextDocumentPrivate *priv, int begin, int end, int f) : p(priv), b(begin), e(end), n(f) {} public: iterator() : p(Q_NULLPTR), b(0), e(0), n(0) {} +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) iterator(const iterator &o) : p(o.p), b(o.b), e(o.e), n(o.n) {} +#endif QTextFragment fragment() const; diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 31dfd20d1a..aceda62a2a 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -38,6 +38,7 @@ #ifndef QT_NO_VALIDATOR #include "private/qobject_p.h" #include "private/qlocale_p.h" +#include "private/qnumeric_p.h" #include <limits.h> #include <cmath> @@ -398,8 +399,8 @@ static qlonglong pow10(int exp) QValidator::State QIntValidator::validate(QString & input, int&) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, - -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, + locale().numberOptions())) { return Invalid; } @@ -438,8 +439,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const void QIntValidator::fixup(QString &input) const { QByteArray buff; - if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, - -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff, -1, + locale().numberOptions())) { return; } bool ok, overflow; @@ -662,8 +663,7 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL { Q_Q(const QDoubleValidator); QByteArray buff; - if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, - locale.numberOptions() & QLocale::RejectGroupSeparator)) { + if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec, locale.numberOptions())) { return QValidator::Invalid; } @@ -676,9 +676,9 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL if (q->t < 0 && buff.startsWith('+')) return QValidator::Invalid; - bool ok, overflow; - double i = QLocaleData::bytearrayToDouble(buff.constData(), &ok, &overflow); - if (overflow) + bool ok = false; + double i = buff.toDouble(&ok); // returns 0.0 if !ok + if (i == qt_qnan()) return QValidator::Invalid; if (!ok) return QValidator::Intermediate; |