summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/image.pri107
-rw-r--r--src/gui/image/qabstractfileiconengine.cpp54
-rw-r--r--src/gui/image/qabstractfileiconengine_p.h42
-rw-r--r--src/gui/image/qabstractfileiconprovider.cpp197
-rw-r--r--src/gui/image/qabstractfileiconprovider.h40
-rw-r--r--src/gui/image/qabstractfileiconprovider_p.h52
-rw-r--r--src/gui/image/qbitmap.cpp69
-rw-r--r--src/gui/image/qbitmap.h41
-rw-r--r--src/gui/image/qbmphandler.cpp204
-rw-r--r--src/gui/image/qbmphandler_p.h40
-rw-r--r--src/gui/image/qicon.cpp779
-rw-r--r--src/gui/image/qicon.h207
-rw-r--r--src/gui/image/qicon_p.h46
-rw-r--r--src/gui/image/qiconengine.cpp127
-rw-r--r--src/gui/image/qiconengine.h40
-rw-r--r--src/gui/image/qiconengine_p.h59
-rw-r--r--src/gui/image/qiconengineplugin.cpp42
-rw-r--r--src/gui/image/qiconengineplugin.h40
-rw-r--r--src/gui/image/qiconloader.cpp481
-rw-r--r--src/gui/image/qiconloader_p.h96
-rw-r--r--src/gui/image/qimage.cpp1531
-rw-r--r--src/gui/image/qimage.h85
-rw-r--r--src/gui/image/qimage_conversions.cpp566
-rw-r--r--src/gui/image/qimage_darwin.mm42
-rw-r--r--src/gui/image/qimage_mips_dspr2.cpp40
-rw-r--r--src/gui/image/qimage_mips_dspr2_asm.S40
-rw-r--r--src/gui/image/qimage_neon.cpp42
-rw-r--r--src/gui/image/qimage_p.h327
-rw-r--r--src/gui/image/qimage_ssse3.cpp40
-rw-r--r--src/gui/image/qimageiohandler.cpp55
-rw-r--r--src/gui/image/qimageiohandler.h43
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp40
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks_p.h40
-rw-r--r--src/gui/image/qimagereader.cpp203
-rw-r--r--src/gui/image/qimagereader.h40
-rw-r--r--src/gui/image/qimagereaderwriterhelpers.cpp81
-rw-r--r--src/gui/image/qimagereaderwriterhelpers_p.h42
-rw-r--r--src/gui/image/qimagewriter.cpp63
-rw-r--r--src/gui/image/qimagewriter.h40
-rw-r--r--src/gui/image/qmovie.cpp137
-rw-r--r--src/gui/image/qmovie.h46
-rw-r--r--src/gui/image/qpaintengine_pic.cpp40
-rw-r--r--src/gui/image/qpaintengine_pic_p.h40
-rw-r--r--src/gui/image/qpicture.cpp44
-rw-r--r--src/gui/image/qpicture.h42
-rw-r--r--src/gui/image/qpicture_p.h40
-rw-r--r--src/gui/image/qpixmap.cpp117
-rw-r--r--src/gui/image/qpixmap.h48
-rw-r--r--src/gui/image/qpixmap_blitter.cpp40
-rw-r--r--src/gui/image/qpixmap_blitter_p.h40
-rw-r--r--src/gui/image/qpixmap_raster.cpp40
-rw-r--r--src/gui/image/qpixmap_raster_p.h40
-rw-r--r--src/gui/image/qpixmap_win.cpp62
-rw-r--r--src/gui/image/qpixmap_win_p.h38
-rw-r--r--src/gui/image/qpixmapcache.cpp231
-rw-r--r--src/gui/image/qpixmapcache.h68
-rw-r--r--src/gui/image/qpixmapcache_p.h43
-rw-r--r--src/gui/image/qplatformpixmap.cpp60
-rw-r--r--src/gui/image/qplatformpixmap.h40
-rw-r--r--src/gui/image/qpnghandler.cpp84
-rw-r--r--src/gui/image/qpnghandler.pri0
-rw-r--r--src/gui/image/qpnghandler_p.h40
-rw-r--r--src/gui/image/qppmhandler.cpp116
-rw-r--r--src/gui/image/qppmhandler_p.h40
-rw-r--r--src/gui/image/qxbmhandler.cpp64
-rw-r--r--src/gui/image/qxbmhandler_p.h40
-rw-r--r--src/gui/image/qxpmhandler.cpp167
-rw-r--r--src/gui/image/qxpmhandler_p.h40
68 files changed, 4242 insertions, 3728 deletions
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
deleted file mode 100644
index f503c97b82..0000000000
--- a/src/gui/image/image.pri
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*-mode:sh-*-
-# Qt image handling
-
-# Qt kernel module
-
-HEADERS += \
- image/qbitmap.h \
- image/qimage.h \
- image/qimage_p.h \
- image/qimageiohandler.h \
- image/qimagereader.h \
- image/qimagereaderwriterhelpers_p.h \
- image/qimagewriter.h \
- image/qpaintengine_pic_p.h \
- image/qpicture.h \
- image/qpicture_p.h \
- image/qpixmap.h \
- image/qpixmap_raster_p.h \
- image/qpixmap_blitter_p.h \
- image/qpixmapcache.h \
- image/qpixmapcache_p.h \
- image/qplatformpixmap.h \
- image/qimagepixmapcleanuphooks_p.h \
- image/qicon.h \
- image/qicon_p.h \
- image/qiconloader_p.h \
- image/qiconengine.h \
- image/qiconengineplugin.h \
- image/qabstractfileiconengine_p.h \
- image/qabstractfileiconprovider.h \
- image/qabstractfileiconprovider_p.h
-
-SOURCES += \
- image/qbitmap.cpp \
- image/qimage.cpp \
- image/qimage_conversions.cpp \
- image/qimageiohandler.cpp \
- image/qimagereader.cpp \
- image/qimagereaderwriterhelpers.cpp \
- image/qimagewriter.cpp \
- image/qpaintengine_pic.cpp \
- image/qpicture.cpp \
- image/qpixmap.cpp \
- image/qpixmapcache.cpp \
- image/qplatformpixmap.cpp \
- image/qpixmap_raster.cpp \
- image/qpixmap_blitter.cpp \
- image/qimagepixmapcleanuphooks.cpp \
- image/qicon.cpp \
- image/qiconloader.cpp \
- image/qiconengine.cpp \
- image/qiconengineplugin.cpp \
- image/qabstractfileiconengine.cpp \
- image/qabstractfileiconprovider.cpp
-
-qtConfig(movie) {
- HEADERS += image/qmovie.h
- SOURCES += image/qmovie.cpp
-}
-
-win32: SOURCES += image/qpixmap_win.cpp
-
-darwin: OBJECTIVE_SOURCES += image/qimage_darwin.mm
-
-# Built-in image format support
-HEADERS += \
- image/qbmphandler_p.h \
- image/qppmhandler_p.h \
- image/qxbmhandler_p.h \
- image/qxpmhandler_p.h
-
-SOURCES += \
- image/qbmphandler.cpp \
- image/qppmhandler.cpp \
- image/qxbmhandler.cpp \
- image/qxpmhandler.cpp
-
-qtConfig(png) {
- HEADERS += image/qpnghandler_p.h
- SOURCES += image/qpnghandler.cpp
- QMAKE_USE_PRIVATE += libpng
-
- win32:mingw {
- # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86048
- GCC_VERSION = "$${QMAKE_GCC_MAJOR_VERSION}.$${QMAKE_GCC_MINOR_VERSION}.$${QMAKE_GCC_PATCH_VERSION}"
- equals(GCC_VERSION, "8.1.0") {
- QMAKE_CXXFLAGS += -fno-reorder-blocks-and-partition
- }
- }
-}
-
-# SIMD
-!android {
- SSSE3_SOURCES += image/qimage_ssse3.cpp
- NEON_SOURCES += image/qimage_neon.cpp
- MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
- MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
-} else {
- # see https://developer.android.com/ndk/guides/abis
- arm64-v8a | armeabi-v7a {
- SOURCES += image/qimage_neon.cpp
- }
- x86 | x86_64 {
- DEFINES += QT_COMPILER_SUPPORTS_SSE2 QT_COMPILER_SUPPORTS_SSE3 QT_COMPILER_SUPPORTS_SSSE3
- SOURCES += image/qimage_ssse3.cpp
- }
-}
diff --git a/src/gui/image/qabstractfileiconengine.cpp b/src/gui/image/qabstractfileiconengine.cpp
index c5800d9119..ffbe088d20 100644
--- a/src/gui/image/qabstractfileiconengine.cpp
+++ b/src/gui/image/qabstractfileiconengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractfileiconengine_p.h"
@@ -43,6 +7,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\class QAbstractFileIconEngine
\brief Helper base class for retrieving icons for files for usage by QFileIconProvider and related.
@@ -73,7 +39,7 @@ QPixmap QAbstractFileIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
if (key.isEmpty())
return filePixmap(size, mode, state);
- key += QLatin1Char('_') + QString::number(size.width());
+ key += u'_' + QString::number(size.width());
QPixmap result;
if (!QPixmapCache::find(key, &result)) {
@@ -85,11 +51,17 @@ QPixmap QAbstractFileIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
return result;
}
+QPixmap QAbstractFileIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+ Q_UNUSED(scale); // (size is pre-multiplied by scale)
+ return pixmap(size, mode, state);
+}
+
QSize QAbstractFileIconEngine::actualSize(const QSize &size, QIcon::Mode mode,
QIcon::State state)
{
const QList<QSize> &sizes = availableSizes(mode, state);
- const int numberSizes = sizes.length();
+ const int numberSizes = sizes.size();
if (numberSizes == 0)
return QSize();
@@ -122,7 +94,7 @@ QString QAbstractFileIconEngine::cacheKey() const
return QString();
const QString &suffix = m_fileInfo.suffix();
- return QLatin1String("qt_.")
+ return "qt_."_L1
+ (suffix.isEmpty() ? m_fileInfo.fileName() : suffix); // handle "Makefile" ;)
}
diff --git a/src/gui/image/qabstractfileiconengine_p.h b/src/gui/image/qabstractfileiconengine_p.h
index 865da58f15..99d16d3224 100644
--- a/src/gui/image/qabstractfileiconengine_p.h
+++ b/src/gui/image/qabstractfileiconengine_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONENGINE_P_H
#define QABSTRACTFILEICONENGINE_P_H
@@ -64,7 +28,9 @@ public:
: QPixmapIconEngine(), m_fileInfo(info), m_options(opts) {}
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State) override;
+ QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State, qreal scale) override;
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ bool isNull() override { return false; }
QFileInfo fileInfo() const { return m_fileInfo; }
QPlatformTheme::IconOptions options() const { return m_options; }
diff --git a/src/gui/image/qabstractfileiconprovider.cpp b/src/gui/image/qabstractfileiconprovider.cpp
index 51638f69d8..71b6a0b03d 100644
--- a/src/gui/image/qabstractfileiconprovider.cpp
+++ b/src/gui/image/qabstractfileiconprovider.cpp
@@ -1,47 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qabstractfileiconprovider.h"
#include <qguiapplication.h>
+#include <private/qguiapplication_p.h>
+#include <qpa/qplatformtheme.h>
#include <qicon.h>
+#if QT_CONFIG(mimetype)
#include <qmimedatabase.h>
+#endif
#include <private/qabstractfileiconprovider_p.h>
@@ -49,12 +17,115 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
QAbstractFileIconProviderPrivate::QAbstractFileIconProviderPrivate(QAbstractFileIconProvider *q)
: q_ptr(q)
{}
QAbstractFileIconProviderPrivate::~QAbstractFileIconProviderPrivate() = default;
+using IconTypeCache = QHash<QAbstractFileIconProvider::IconType, QIcon>;
+Q_GLOBAL_STATIC(IconTypeCache, iconTypeCache)
+
+void QAbstractFileIconProviderPrivate::clearIconTypeCache()
+{
+ iconTypeCache()->clear();
+}
+
+QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(QAbstractFileIconProvider::IconType type) const
+{
+ auto theme = QGuiApplicationPrivate::platformTheme();
+ if (theme == nullptr)
+ return {};
+
+ auto &cache = *iconTypeCache();
+ auto it = cache.find(type);
+ if (it == cache.end()) {
+ const auto sp = [&]() -> QPlatformTheme::StandardPixmap {
+ switch (type) {
+ case QAbstractFileIconProvider::Computer:
+ return QPlatformTheme::ComputerIcon;
+ case QAbstractFileIconProvider::Desktop:
+ return QPlatformTheme::DesktopIcon;
+ case QAbstractFileIconProvider::Trashcan:
+ return QPlatformTheme::TrashIcon;
+ case QAbstractFileIconProvider::Network:
+ return QPlatformTheme::DriveNetIcon;
+ case QAbstractFileIconProvider::Drive:
+ return QPlatformTheme::DriveHDIcon;
+ case QAbstractFileIconProvider::Folder:
+ return QPlatformTheme::DirIcon;
+ case QAbstractFileIconProvider::File:
+ break;
+ // no default on purpose; we want warnings when the type enum is extended
+ }
+ return QPlatformTheme::FileIcon;
+ }();
+
+ const auto sizesHint = theme->themeHint(QPlatformTheme::IconPixmapSizes);
+ auto sizes = sizesHint.value<QList<QSize>>();
+ if (sizes.isEmpty())
+ sizes.append({64, 64});
+
+ QIcon icon;
+ for (const auto &size : sizes)
+ icon.addPixmap(theme->standardPixmap(sp, size));
+ it = cache.insert(type, icon);
+ }
+ return it.value();
+}
+
+QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(QAbstractFileIconProvider::IconType type) const
+{
+ switch (type) {
+ case QAbstractFileIconProvider::Computer:
+ return QIcon::fromTheme("computer"_L1);
+ case QAbstractFileIconProvider::Desktop:
+ return QIcon::fromTheme("user-desktop"_L1);
+ case QAbstractFileIconProvider::Trashcan:
+ return QIcon::fromTheme("user-trash"_L1);
+ case QAbstractFileIconProvider::Network:
+ return QIcon::fromTheme("network-workgroup"_L1);
+ case QAbstractFileIconProvider::Drive:
+ return QIcon::fromTheme("drive-harddisk"_L1);
+ case QAbstractFileIconProvider::Folder:
+ return QIcon::fromTheme("folder"_L1);
+ case QAbstractFileIconProvider::File:
+ return QIcon::fromTheme("text-x-generic"_L1);
+ // no default on purpose; we want warnings when the type enum is extended
+ }
+ return QIcon::fromTheme("text-x-generic"_L1);
+}
+
+static inline QPlatformTheme::IconOptions toThemeIconOptions(QAbstractFileIconProvider::Options options)
+{
+ QPlatformTheme::IconOptions result;
+ if (options.testFlag(QAbstractFileIconProvider::DontUseCustomDirectoryIcons))
+ result |= QPlatformTheme::DontUseCustomDirectoryIcons;
+ return result;
+}
+
+QIcon QAbstractFileIconProviderPrivate::getPlatformThemeIcon(const QFileInfo &info) const
+{
+ if (auto theme = QGuiApplicationPrivate::platformTheme())
+ return theme->fileIcon(info, toThemeIconOptions(options));
+ return {};
+}
+
+QIcon QAbstractFileIconProviderPrivate::getIconThemeIcon(const QFileInfo &info) const
+{
+ if (info.isRoot())
+ return getIconThemeIcon(QAbstractFileIconProvider::Drive);
+ if (info.isDir())
+ return getIconThemeIcon(QAbstractFileIconProvider::Folder);
+#if QT_CONFIG(mimetype)
+ return QIcon::fromTheme(mimeDatabase.mimeTypeForFile(info).iconName());
+#else
+ return QIcon::fromTheme("text-x-generic"_L1);
+#endif
+}
+
/*!
\class QAbstractFileIconProvider
@@ -139,25 +210,9 @@ QAbstractFileIconProvider::Options QAbstractFileIconProvider::options() const
QIcon QAbstractFileIconProvider::icon(IconType type) const
{
- Q_UNUSED(type);
- switch (type) {
- case Computer:
- return QIcon::fromTheme(QLatin1String("computer"));
- case Desktop:
- return QIcon::fromTheme(QLatin1String("user-desktop"));
- case Trashcan:
- return QIcon::fromTheme(QLatin1String("user-trash"));
- case Network:
- return QIcon::fromTheme(QLatin1String("network-workgroup"));
- case Drive:
- return QIcon::fromTheme(QLatin1String("drive-harddisk"));
- case Folder:
- return QIcon::fromTheme(QLatin1String("folder"));
- case File:
- return QIcon::fromTheme(QLatin1String("text-x-generic"));
- // no default on purpose; we want warnings when the type enum is extended
- }
- return QIcon::fromTheme(QLatin1String("text-x-generic"));
+ Q_D(const QAbstractFileIconProvider);
+ const QIcon result = d->getIconThemeIcon(type);
+ return result.isNull() ? d->getPlatformThemeIcon(type) : result;
}
/*!
@@ -170,25 +225,22 @@ QIcon QAbstractFileIconProvider::icon(IconType type) const
QIcon QAbstractFileIconProvider::icon(const QFileInfo &info) const
{
Q_D(const QAbstractFileIconProvider);
- if (info.isRoot())
- return icon(Drive);
- if (info.isDir())
- return icon(Folder);
- return QIcon::fromTheme(d->mimeDatabase.mimeTypeForFile(info).iconName());
+ const QIcon result = d->getIconThemeIcon(info);
+ return result.isNull() ? d->getPlatformThemeIcon(info) : result;
}
-/*!
- Returns the type of the file described by \a info.
-*/
-QString QAbstractFileIconProvider::type(const QFileInfo &info) const
+QString QAbstractFileIconProviderPrivate::getFileType(const QFileInfo &info)
{
- Q_D(const QAbstractFileIconProvider);
if (QFileSystemEntry::isRootPath(info.absoluteFilePath()))
return QGuiApplication::translate("QAbstractFileIconProvider", "Drive");
if (info.isFile()) {
- const QMimeType mimeType = d->mimeDatabase.mimeTypeForFile(info);
+#if QT_CONFIG(mimetype)
+ const QMimeType mimeType = QMimeDatabase().mimeTypeForFile(info);
return mimeType.comment().isEmpty() ? mimeType.name() : mimeType.comment();
+#else
+ return QGuiApplication::translate("QAbstractFileIconProvider", "File");
+#endif
}
if (info.isDir())
@@ -216,4 +268,13 @@ QString QAbstractFileIconProvider::type(const QFileInfo &info) const
return QGuiApplication::translate("QAbstractFileIconProvider", "Unknown");
}
+/*!
+ Returns the type of the file described by \a info.
+*/
+
+QString QAbstractFileIconProvider::type(const QFileInfo &info) const
+{
+ return QAbstractFileIconProviderPrivate::getFileType(info);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qabstractfileiconprovider.h b/src/gui/image/qabstractfileiconprovider.h
index fc107e0ca3..df5f642521 100644
--- a/src/gui/image/qabstractfileiconprovider.h
+++ b/src/gui/image/qabstractfileiconprovider.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONPROVIDER_H
#define QABSTRACTFILEICONPROVIDER_H
diff --git a/src/gui/image/qabstractfileiconprovider_p.h b/src/gui/image/qabstractfileiconprovider_p.h
index 53ad4826eb..f53be0f06c 100644
--- a/src/gui/image/qabstractfileiconprovider_p.h
+++ b/src/gui/image/qabstractfileiconprovider_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QABSTRACTFILEICONPROVIDER_P_H
#define QABSTRACTFILEICONPROVIDER_P_H
@@ -52,7 +16,9 @@
//
#include <QtGui/private/qtguiglobal_p.h>
+#if QT_CONFIG(mimetype)
#include <QtCore/QMimeDatabase>
+#endif
#include "qabstractfileiconprovider.h"
QT_BEGIN_NAMESPACE
@@ -65,10 +31,20 @@ public:
QAbstractFileIconProviderPrivate(QAbstractFileIconProvider *q);
virtual ~QAbstractFileIconProviderPrivate();
+ QIcon getPlatformThemeIcon(QAbstractFileIconProvider::IconType type) const;
+ QIcon getIconThemeIcon(QAbstractFileIconProvider::IconType type) const;
+ QIcon getPlatformThemeIcon(const QFileInfo &info) const;
+ QIcon getIconThemeIcon(const QFileInfo &info) const;
+
+ static void clearIconTypeCache();
+ static QString getFileType(const QFileInfo &info);
+
QAbstractFileIconProvider *q_ptr = nullptr;
QAbstractFileIconProvider::Options options = {};
+#if QT_CONFIG(mimetype)
QMimeDatabase mimeDatabase;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 0505717fb3..2208cca1be 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitmap.h"
#include <qpa/qplatformpixmap.h>
@@ -46,6 +10,8 @@
#include <qpainter.h>
#include <private/qguiapplication_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
/*!
@@ -114,25 +80,31 @@ QBitmap::QBitmap()
\sa clear()
*/
-
QBitmap::QBitmap(int w, int h)
: QPixmap(QSize(w, h), QPlatformPixmap::BitmapType)
{
}
/*!
+ \deprecated [6.0] Use fromPixmap instead.
+
Constructs a bitmap with the given \a size. The pixels in the
bitmap are uninitialized.
\sa clear()
*/
-
QBitmap::QBitmap(const QSize &size)
: QPixmap(size, QPlatformPixmap::BitmapType)
{
}
/*!
+ \internal
+ This dtor must stay empty until Qt 7 (was inline until 6.2).
+*/
+QBitmap::~QBitmap() = default;
+
+/*!
\fn QBitmap::clear()
Clears the bitmap, setting all its bits to Qt::color0.
@@ -149,7 +121,6 @@ QBitmap::QBitmap(const QSize &size)
\sa QPixmap::isNull(), QImageReader::imageFormat()
*/
-
QBitmap::QBitmap(const QString& fileName, const char *format)
: QPixmap(QSize(0, 0), QPlatformPixmap::BitmapType)
{
@@ -184,10 +155,10 @@ static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags)
image.setColor(1, c0);
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType));
data->fromImageInPlace(image, flags | Qt::MonoOnly);
- return QBitmap::fromPixmap(QPixmap(data.take()));
+ return QBitmap::fromPixmap(QPixmap(data.release()));
}
/*!
@@ -225,7 +196,7 @@ QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags)
Constructs a bitmap with the given \a size, and sets the contents to
the \a bits supplied.
- The bitmap data has to be byte aligned and provided in in the bit
+ The bitmap data has to be byte aligned and provided in the bit
order specified by \a monoFormat. The mono format must be either
QImage::Format_Mono or QImage::Format_MonoLSB. Use
QImage::Format_Mono to specify data on the XBM format.
@@ -241,7 +212,7 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m
image.setColor(0, QColor(Qt::color0).rgb());
image.setColor(1, QColor(Qt::color1).rgb());
- // Need to memcpy each line separatly since QImage is 32bit aligned and
+ // Need to memcpy each line separately since QImage is 32bit aligned and
// this data is only byte aligned...
int bytesPerLine = (size.width() + 7) / 8;
for (int y = 0; y < size.height(); ++y)
@@ -255,6 +226,8 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m
If the pixmap has a depth greater than 1, the resulting bitmap
will be dithered automatically.
+ \since 6.0
+
\sa QPixmap::depth()
*/
@@ -277,7 +250,7 @@ QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
#if QT_DEPRECATED_SINCE(6, 0)
/*!
- \obsolete Use fromPixmap instead.
+ \deprecated [6.0] Use fromPixmap instead.
Constructs a bitmap that is a copy of the given \a pixmap.
If the pixmap has a depth greater than 1, the resulting bitmap
@@ -285,14 +258,13 @@ QBitmap QBitmap::fromPixmap(const QPixmap &pixmap)
\sa QPixmap::depth(), fromImage(), fromData()
*/
-
QBitmap::QBitmap(const QPixmap &pixmap)
{
*this = QBitmap::fromPixmap(pixmap);
}
/*!
- \obsolete Use fromPixmap instead.
+ \deprecated [6.0] Use fromPixmap instead.
\overload
Assigns the given \a pixmap to this bitmap and returns a reference
@@ -303,7 +275,6 @@ QBitmap::QBitmap(const QPixmap &pixmap)
\sa QPixmap::depth()
*/
-
QBitmap &QBitmap::operator=(const QPixmap &pixmap)
{
*this = QBitmap::fromPixmap(pixmap);
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index 9052e62db6..77d276ab14 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBITMAP_H
#define QBITMAP_H
@@ -58,6 +22,7 @@ public:
QBitmap(int w, int h);
explicit QBitmap(const QSize &);
explicit QBitmap(const QString &fileName, const char *format = nullptr);
+ ~QBitmap() override;
#if QT_DEPRECATED_SINCE(6, 0)
QT_DEPRECATED_VERSION_X_6_0("Use fromPixmap instead.") QBitmap &operator=(const QPixmap &);
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 74df9820e4..798ba7f4b3 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qbmphandler_p.h"
@@ -104,6 +68,7 @@ const int BMP_RGB = 0; // no compression
const int BMP_RLE8 = 1; // run-length encoded, 8 bits
const int BMP_RLE4 = 2; // run-length encoded, 4 bits
const int BMP_BITFIELDS = 3; // RGB values encoded in data as bit-fields
+const int BMP_ALPHABITFIELDS = 4; // RGBA values encoded in data as bit-fields
static QDataStream &operator>>(QDataStream &s, BMP_INFOHDR &bi)
@@ -147,19 +112,65 @@ static QDataStream &operator<<(QDataStream &s, const BMP_INFOHDR &bi)
s << bi.biSizeImage;
s << bi.biXPelsPerMeter << bi.biYPelsPerMeter;
s << bi.biClrUsed << bi.biClrImportant;
+
+ if (bi.biSize >= BMP_WIN4) {
+ s << bi.biRedMask << bi.biGreenMask << bi.biBlueMask << bi.biAlphaMask;
+ s << bi.biCSType;
+
+ for (int i = 0; i < 9; i++)
+ s << bi.biEndpoints[i];
+
+ s << bi.biGammaRed;
+ s << bi.biGammaGreen;
+ s << bi.biGammaBlue;
+ }
+
+ if (bi.biSize >= BMP_WIN5) {
+ s << bi.biIntent;
+ s << bi.biProfileData;
+ s << bi.biProfileSize;
+ s << bi.biReserved;
+ }
+
return s;
}
-static int calc_shift(uint mask)
+static uint calc_shift(uint mask)
{
- int result = 0;
- while (mask && !(mask & 1)) {
+ uint result = 0;
+ while ((mask >= 0x100) || (!(mask & 1) && mask)) {
result++;
mask >>= 1;
}
return result;
}
+static uint calc_scale(uint low_mask)
+{
+ uint result = 8;
+ while (low_mask && result) {
+ result--;
+ low_mask >>= 1;
+ }
+ return result;
+}
+
+static inline uint apply_scale(uint value, uint scale)
+{
+ if (!(scale & 0x07)) // return immediately if scale == 8 or 0
+ return value;
+
+ uint filled = 8 - scale;
+ uint result = value << scale;
+
+ do {
+ result |= result >> filled;
+ filled <<= 1;
+ } while (filled < 8);
+
+ return result;
+}
+
static bool read_dib_fileheader(QDataStream &s, BMP_FILEHDR &bf)
{
// read BMP file header
@@ -196,13 +207,13 @@ static bool read_dib_infoheader(QDataStream &s, BMP_INFOHDR &bi)
return true;
}
-static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset, qint64 startpos, QImage &image)
+static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 datapos, qint64 startpos, QImage &image)
{
QIODevice* d = s.device();
if (d->atEnd()) // end of stream/file
return false;
#if 0
- qDebug("offset...........%lld", offset);
+ qDebug("offset...........%lld", datapos);
qDebug("startpos.........%lld", startpos);
qDebug("biSize...........%d", bi.biSize);
qDebug("biWidth..........%d", bi.biWidth);
@@ -222,33 +233,38 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
uint green_mask = 0;
uint blue_mask = 0;
uint alpha_mask = 0;
- int red_shift = 0;
- int green_shift = 0;
- int blue_shift = 0;
- int alpha_shift = 0;
- int red_scale = 0;
- int green_scale = 0;
- int blue_scale = 0;
- int alpha_scale = 0;
+ uint red_shift = 0;
+ uint green_shift = 0;
+ uint blue_shift = 0;
+ uint alpha_shift = 0;
+ uint red_scale = 0;
+ uint green_scale = 0;
+ uint blue_scale = 0;
+ uint alpha_scale = 0;
+ bool bitfields = comp == BMP_BITFIELDS || comp == BMP_ALPHABITFIELDS;
if (!d->isSequential())
- d->seek(startpos + BMP_FILEHDR_SIZE + bi.biSize); // goto start of colormap or masks
+ d->seek(startpos + bi.biSize); // goto start of colormap or masks
if (bi.biSize >= BMP_WIN4) {
red_mask = bi.biRedMask;
green_mask = bi.biGreenMask;
blue_mask = bi.biBlueMask;
alpha_mask = bi.biAlphaMask;
- } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
+ } else if (bitfields && (nbits == 16 || nbits == 32)) {
if (d->read((char *)&red_mask, sizeof(red_mask)) != sizeof(red_mask))
return false;
if (d->read((char *)&green_mask, sizeof(green_mask)) != sizeof(green_mask))
return false;
if (d->read((char *)&blue_mask, sizeof(blue_mask)) != sizeof(blue_mask))
return false;
+ if (comp == BMP_ALPHABITFIELDS && d->read((char *)&alpha_mask, sizeof(alpha_mask)) != sizeof(alpha_mask))
+ return false;
}
- bool transp = (comp == BMP_BITFIELDS) && alpha_mask;
+ bool transp = bitfields || (comp == BMP_RGB && nbits == 32 && alpha_mask == 0xff000000);
+ transp = transp && alpha_mask;
+
int ncols = 0;
int depth = 0;
QImage::Format format;
@@ -295,23 +311,23 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
if (d->atEnd()) // truncated file
return false;
}
- } else if (comp == BMP_BITFIELDS && (nbits == 16 || nbits == 32)) {
+ } else if (bitfields && (nbits == 16 || nbits == 32)) {
red_shift = calc_shift(red_mask);
if (((red_mask >> red_shift) + 1) == 0)
return false;
- red_scale = 256 / ((red_mask >> red_shift) + 1);
+ red_scale = calc_scale(red_mask >> red_shift);
green_shift = calc_shift(green_mask);
if (((green_mask >> green_shift) + 1) == 0)
return false;
- green_scale = 256 / ((green_mask >> green_shift) + 1);
+ green_scale = calc_scale(green_mask >> green_shift);
blue_shift = calc_shift(blue_mask);
if (((blue_mask >> blue_shift) + 1) == 0)
return false;
- blue_scale = 256 / ((blue_mask >> blue_shift) + 1);
+ blue_scale = calc_scale(blue_mask >> blue_shift);
alpha_shift = calc_shift(alpha_mask);
if (((alpha_mask >> alpha_shift) + 1) == 0)
return false;
- alpha_scale = 256 / ((alpha_mask >> alpha_shift) + 1);
+ alpha_scale = calc_scale(alpha_mask >> alpha_shift);
} else if (comp == BMP_RGB && (nbits == 24 || nbits == 32)) {
blue_mask = 0x000000ff;
green_mask = 0x0000ff00;
@@ -319,17 +335,21 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
blue_shift = 0;
green_shift = 8;
red_shift = 16;
- blue_scale = green_scale = red_scale = 1;
+ blue_scale = green_scale = red_scale = 0;
+ if (transp) {
+ alpha_shift = calc_shift(alpha_mask);
+ if (((alpha_mask >> alpha_shift) + 1) == 0)
+ return false;
+ alpha_scale = calc_scale(alpha_mask >> alpha_shift);
+ }
} else if (comp == BMP_RGB && nbits == 16) {
blue_mask = 0x001f;
green_mask = 0x03e0;
red_mask = 0x7c00;
blue_shift = 0;
- green_shift = 2;
- red_shift = 7;
- red_scale = 1;
- green_scale = 1;
- blue_scale = 8;
+ green_shift = 5;
+ red_shift = 10;
+ blue_scale = green_scale = red_scale = 3;
}
image.setDotsPerMeterX(bi.biXPelsPerMeter);
@@ -342,10 +362,9 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
qDebug("Amask: %08x Ashift: %08x Ascale:%08x", alpha_mask, alpha_shift, alpha_scale);
#endif
- // offset can be bogus, be careful
- if (offset>=0 && startpos + offset > d->pos()) {
+ if (datapos >= 0 && datapos > d->pos()) {
if (!d->isSequential())
- d->seek(startpos + offset); // start of image data
+ d->seek(datapos); // start of image data
}
int bpl = image.bytesPerLine();
@@ -538,10 +557,10 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
c |= *(uchar*)(b+2)<<16;
if (nbits > 24)
c |= *(uchar*)(b+3)<<24;
- *p++ = qRgba(((c & red_mask) >> red_shift) * red_scale,
- ((c & green_mask) >> green_shift) * green_scale,
- ((c & blue_mask) >> blue_shift) * blue_scale,
- transp ? ((c & alpha_mask) >> alpha_shift) * alpha_scale : 0xff);
+ *p++ = qRgba(apply_scale((c & red_mask) >> red_shift, red_scale),
+ apply_scale((c & green_mask) >> green_shift, green_scale),
+ apply_scale((c & blue_mask) >> blue_shift, blue_scale),
+ transp ? apply_scale((c & alpha_mask) >> alpha_shift, alpha_scale) : 0xff);
b += nbits/8;
}
}
@@ -563,7 +582,6 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, qint64 offset,
return true;
}
-// this is also used in qmime_win.cpp
bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int nbits)
{
QIODevice* d = s.device();
@@ -590,7 +608,7 @@ bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int
if (image.depth() != 32) { // write color table
uchar *color_table = new uchar[4*image.colorCount()];
uchar *rgb = color_table;
- QList<QRgb> c = image.colorTable();
+ const QList<QRgb> c = image.colorTable();
for (int i = 0; i < image.colorCount(); i++) {
*rgb++ = qBlue (c[i]);
*rgb++ = qGreen(c[i]);
@@ -650,15 +668,6 @@ bool qt_write_dib(QDataStream &s, const QImage &image, int bpl, int bpl_bmp, int
return true;
}
-// this is also used in qmime_win.cpp
-bool qt_read_dib(QDataStream &s, QImage &image)
-{
- BMP_INFOHDR bi;
- if (!read_dib_infoheader(s, bi))
- return false;
- return read_dib_body(s, bi, -1, -BMP_FILEHDR_SIZE, image);
-}
-
QBmpHandler::QBmpHandler(InternalFormat fmt) :
m_format(fmt), state(Ready)
{
@@ -741,9 +750,32 @@ bool QBmpHandler::read(QImage *image)
s.setByteOrder(QDataStream::LittleEndian);
// read image
+ qint64 datapos = startpos;
+ if (m_format == BmpFormat) {
+ datapos += fileHeader.bfOffBits;
+ } else {
+ // QTBUG-100351: We have no file header when reading dib format so we have to depend on the size of the
+ // buffer and the biSizeImage value to find where the pixel data starts since there's sometimes optional
+ // color mask values after biSize, like for example when pasting from the windows snipping tool.
+ if (infoHeader.biSizeImage > 0 && infoHeader.biSizeImage < d->size()) {
+ datapos = d->size() - infoHeader.biSizeImage;
+ } else {
+ // And sometimes biSizeImage is not filled in like when pasting from Microsoft Edge, so then we just
+ // have to assume the optional color mask values are there.
+ datapos += infoHeader.biSize;
+
+ if (infoHeader.biBitCount == 16 || infoHeader.biBitCount == 32) {
+ if (infoHeader.biCompression == BMP_BITFIELDS) {
+ datapos += 12;
+ } else if (infoHeader.biCompression == BMP_ALPHABITFIELDS) {
+ datapos += 16;
+ }
+ }
+ }
+ }
const bool readSuccess = m_format == BmpFormat ?
- read_dib_body(s, infoHeader, fileHeader.bfOffBits, startpos, *image) :
- read_dib_body(s, infoHeader, -1, startpos - BMP_FILEHDR_SIZE, *image);
+ read_dib_body(s, infoHeader, datapos, startpos + BMP_FILEHDR_SIZE, *image) :
+ read_dib_body(s, infoHeader, datapos, startpos, *image);
if (!readSuccess)
return false;
@@ -847,7 +879,7 @@ QVariant QBmpHandler::option(ImageOption option) const
case 32:
case 24:
case 16:
- if (infoHeader.biCompression == BMP_BITFIELDS && infoHeader.biSize >= BMP_WIN4 && infoHeader.biAlphaMask)
+ if ((infoHeader.biCompression == BMP_BITFIELDS || infoHeader.biCompression == BMP_ALPHABITFIELDS) && infoHeader.biSize >= BMP_WIN4 && infoHeader.biAlphaMask)
format = QImage::Format_ARGB32;
else
format = QImage::Format_RGB32;
diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h
index e1d744e539..0ba0946afe 100644
--- a/src/gui/image/qbmphandler_p.h
+++ b/src/gui/image/qbmphandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QBMPHANDLER_P_H
#define QBMPHANDLER_P_H
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 0bbc4005a0..086ac37a07 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qicon.h"
#include "qicon_p.h"
@@ -61,11 +25,14 @@
#include "private/qhexstring_p.h"
#include "private/qguiapplication_p.h"
+#include "private/qoffsetstringarray_p.h"
#include "qpa/qplatformtheme.h"
#ifndef QT_NO_ICON
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
/*!
\enum QIcon::Mode
@@ -101,7 +68,7 @@ QT_BEGIN_NAMESPACE
static int nextSerialNumCounter()
{
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
return 1 + serial.fetchAndAddRelaxed(1);
}
@@ -132,6 +99,11 @@ QIconPrivate::QIconPrivate(QIconEngine *e)
{
}
+void QIconPrivate::clearIconCache()
+{
+ qt_cleanup_icon_cache();
+}
+
/*! \internal
Computes the displayDevicePixelRatio for a pixmap.
@@ -174,7 +146,7 @@ void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode
auto paintDevice = painter->device();
qreal dpr = paintDevice ? paintDevice->devicePixelRatio() : qApp->devicePixelRatio();
const QSize pixmapSize = rect.size() * dpr;
- QPixmap px = pixmap(pixmapSize, mode, state);
+ QPixmap px = scaledPixmap(pixmapSize, mode, state, dpr);
painter->drawPixmap(rect, px);
}
@@ -192,12 +164,15 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
// scale: we can only differentiate on scale if the scale differs
if (pa->scale != pb->scale) {
- // Score the pixmaps: 0 is an exact scale match, postive
+ // Score the pixmaps: 0 is an exact scale match, positive
// scores have more detail than requested, negative scores
- // have less detail than rquested.
+ // have less detail than requested.
qreal ascore = pa->scale - scale;
qreal bscore = pb->scale - scale;
+ // always prefer positive scores to prevent upscaling
+ if ((ascore < 0) != (bscore < 0))
+ return bscore < 0 ? pa : pb;
// Take the one closest to 0
return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
}
@@ -226,7 +201,7 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
{
QPixmapIconEngineEntry *pe = nullptr;
- for (int i = 0; i < pixmaps.count(); ++i)
+ for (int i = 0; i < pixmaps.size(); ++i)
if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
if (pe)
pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
@@ -303,7 +278,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
pm = pe->pixmap;
if (pm.isNull()) {
- int idx = pixmaps.count();
+ int idx = pixmaps.size();
while (--idx >= 0) {
if (pe == &pixmaps.at(idx)) {
pixmaps.remove(idx);
@@ -320,7 +295,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
- QString key = QLatin1String("qt_")
+ QString key = "qt_"_L1
% HexString<quint64>(pm.cacheKey())
% HexString<uint>(pe ? pe->mode : QIcon::Normal)
% HexString<quint64>(QGuiApplication::palette().cacheKey())
@@ -358,7 +333,7 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
{
QSize actualSize;
- // The returned actiual size is the size in device independent pixels,
+ // The returned actual size is the size in device independent pixels,
// so we limit the search to scale 1 and assume that e.g. @2x versions
// does not proviode extra actual sizes not also provided by the 1x versions.
qreal scale = 1;
@@ -377,15 +352,16 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
{
QList<QSize> sizes;
- for (int i = 0; i < pixmaps.size(); ++i) {
- QPixmapIconEngineEntry &pe = pixmaps[i];
- if (pe.size == QSize() && pe.pixmap.isNull()) {
+ for (QPixmapIconEngineEntry &pe : pixmaps) {
+ if (pe.mode != mode || pe.state != state)
+ continue;
+ if (pe.size.isEmpty() && pe.pixmap.isNull()) {
pe.pixmap = QPixmap(pe.fileName);
pe.size = pe.pixmap.size();
}
- if (pe.mode == mode && pe.state == state && !pe.size.isEmpty())
+ if (!pe.size.isEmpty() && !sizes.contains(pe.size))
sizes.push_back(pe.size);
- }
+ }
return sizes;
}
@@ -450,7 +426,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
{
if (fileName.isEmpty())
return;
- const QString abs = fileName.startsWith(QLatin1Char(':')) ? fileName : QFileInfo(fileName).absoluteFilePath();
+ const QString abs = fileName.startsWith(u':') ? fileName : QFileInfo(fileName).absoluteFilePath();
const bool ignoreSize = !size.isValid();
ImageReader imageReader(abs);
const QByteArray format = imageReader.format();
@@ -485,15 +461,20 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco
}
}
}
- for (const QImage &i : qAsConst(icoImages))
+ for (const QImage &i : std::as_const(icoImages))
pixmaps += QPixmapIconEngineEntry(abs, i, mode, state);
if (icoImages.isEmpty() && !ignoreSize) // Add placeholder with the filename and empty pixmap for the size.
pixmaps += QPixmapIconEngineEntry(abs, size, mode, state);
}
+bool QPixmapIconEngine::isNull()
+{
+ return pixmaps.isEmpty();
+}
+
QString QPixmapIconEngine::key() const
{
- return QLatin1String("QPixmapIconEngine");
+ return "QPixmapIconEngine"_L1;
}
QIconEngine *QPixmapIconEngine::clone() const
@@ -549,12 +530,12 @@ bool QPixmapIconEngine::write(QDataStream &out) const
return true;
}
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QIconEngineFactoryInterface_iid, QLatin1String("/iconengines"), Qt::CaseInsensitive))
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, iceLoader,
+ (QIconEngineFactoryInterface_iid, "/iconengines"_L1, Qt::CaseInsensitive))
QFactoryLoader *qt_iconEngineFactoryLoader()
{
- return loader();
+ return iceLoader();
}
@@ -570,15 +551,26 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
A QIcon can generate smaller, larger, active, and disabled pixmaps
from the set of pixmaps it is given. Such pixmaps are used by Qt
- widgets to show an icon representing a particular action.
+ UI components to show an icon representing a particular action.
- The simplest use of QIcon is to create one from a QPixmap file or
- resource, and then use it, allowing Qt to work out all the required
- icon styles and sizes. For example:
+ \section1 Creating an icon from image files
+
+ The simplest way to construct a QIcon is to create one from one or
+ several image files or resources. For example:
\snippet code/src_gui_image_qicon.cpp 0
- To undo a QIcon, simply set a null icon in its place:
+ QIcon can store several images for different states, and Qt will
+ select the image that is the closest match for the action's current
+ state.
+
+ \snippet code/src_gui_image_qicon.cpp addFile
+
+ Qt will generate the required icon styles and sizes when needed,
+ e.g. the pixmap for the QIcon::Disabled state might be generated by
+ graying out one of the provided pixmaps.
+
+ To clear the icon, simply set a null icon in its place:
\snippet code/src_gui_image_qicon.cpp 1
@@ -586,31 +578,54 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
QImageWriter::supportedImageFormats() functions to retrieve a
complete list of the supported file formats.
- When you retrieve a pixmap using pixmap(QSize, Mode, State), and no
- pixmap for this given size, mode and state has been added with
- addFile() or addPixmap(), then QIcon will generate one on the
- fly. This pixmap generation happens in a QIconEngine. The default
- engine scales pixmaps down if required, but never up, and it uses
- the current style to calculate a disabled appearance. By using
- custom icon engines, you can customize every aspect of generated
- icons. With QIconEnginePlugin it is possible to register different
- icon engines for different file suffixes, making it possible for
- third parties to provide additional icon engines to those included
+ \section1 Creating an icon from a theme or icon library
+
+ The most convenient way to construct an icon is by using the
+ \l{QIcon::}{fromTheme()} factory function. Qt implements access to
+ the native icon library on platforms that support the
+ \l {Freedesktop Icon Theme Specification}. Since Qt 6.7, Qt also
+ provides access to the native icon library on macOS, iOS, and
+ Windows 10 and 11. On Android, Qt can access icons from the Material
+ design system as long as the
+ \l{https://github.com/google/material-design-icons/tree/master/font}
+ {MaterialIcons-Regular} font is available on the system, or bundled
+ as a resource at \c{:/qt-project.org/icons/MaterialIcons-Regular.ttf}
+ with the application.
+
+ \snippet code/src_gui_image_qicon.cpp fromTheme
+
+ Applications can use the same theming specification to provide
+ their own icon library. See below for an example theme description
+ and the corresponding directory structure for the image files.
+ Icons from an application-provided theme take precedence over the
+ native icon library.
+
+ In addition, it is possible to provide custom \l {QIconEngine}
+ {icon engines}. This allows applications to customize every aspect
+ of generated icons. With QIconEnginePlugin it is possible to register
+ different icon engines for different file suffixes, making it possible
+ for third parties to provide additional icon engines to those included
with Qt.
- \note Since Qt 4.2, an icon engine that supports SVG is included.
-
\section1 Making Classes that Use QIcon
If you write your own widgets that have an option to set a small
pixmap, consider allowing a QIcon to be set for that pixmap. The
Qt class QToolButton is an example of such a widget.
- Provide a method to set a QIcon, and when you draw the icon, choose
- whichever pixmap is appropriate for the current state of your widget.
- For example:
+ Provide a method to set a QIcon, and paint the QIcon with
+ \l{QIcon::}{paint}, choosing the appropriate parameters based
+ on the current state of your widget. For example:
+
\snippet code/src_gui_image_qicon.cpp 2
+ When you retrieve a pixmap using pixmap(QSize, Mode, State), and no
+ pixmap for this given size, mode and state has been added with
+ addFile() or addPixmap(), then QIcon will generate one on the
+ fly. This pixmap generation happens in a QIconEngine. The default
+ engine scales pixmaps down if required, but never up, and it uses
+ the current style to calculate a disabled appearance.
+
You might also make use of the \c Active mode, perhaps making your
widget \c Active when the mouse is over the widget (see \l
QWidget::enterEvent()), while the mouse is pressed pending the
@@ -624,17 +639,19 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
\section1 High DPI Icons
- There are two ways that QIcon supports \l {High DPI Displays}{high DPI}
- icons: via \l addFile() and \l fromTheme().
+ Icons that are provided by the native icon library are usually based
+ on vector graphics, and will automatically be rendered in the appropriate
+ resolution.
- \l addFile() is useful if you have your own custom directory structure and do
- not need to use the \l {Icon Theme Specification}{freedesktop.org Icon Theme
- Specification}. Icons created via this approach use Qt's \l {High Resolution
- Versions of Images}{"@nx" high DPI syntax}.
+ When providing your own image files via \l addFile(), then QIcon will
+ use Qt's \l {High Resolution Versions of Images}{"@nx" high DPI syntax}.
+ This is useful if you have your own custom directory structure and do not
+ use follow \l {Freedesktop Icon Theme Specification}.
- Using \l fromTheme() is necessary if you plan on following the Icon Theme
- Specification. To make QIcon use the high DPI version of an image, add an
- additional entry to the appropriate \c index.theme file:
+ When providing an application theme, then you need to follow the Icon Theme
+ Specification to specify which files to use for different resolutions.
+ To make QIcon use the high DPI version of an image, add an additional entry
+ to the appropriate \c index.theme file:
\badcode
[Icon Theme]
@@ -666,8 +683,6 @@ QFactoryLoader *qt_iconEngineFactoryLoader()
│ └── appointment-new.png
└── index.theme
\endcode
-
- \sa {fowler}{GUI Design Handbook: Iconic Label}, {Icons Example}
*/
@@ -876,7 +891,7 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat
#if QT_DEPRECATED_SINCE(6, 0)
/*!
\since 5.1
- \deprecated
+ \deprecated [6.0] Use pixmap(size, devicePixelRatio) instead.
Returns a pixmap with the requested \a window \a size, \a mode, and \a
state, generating one if necessary.
@@ -885,8 +900,6 @@ QPixmap QIcon::pixmap(const QSize &size, qreal devicePixelRatio, Mode mode, Stat
a high-dpi display the pixmap can be larger. In that case it will have
a devicePixelRatio larger than 1.
- \obsolete Use the overload which takes qreal devicePixelRatio instead.
-
\sa actualSize(), paint()
*/
@@ -926,6 +939,7 @@ QSize QIcon::actualSize(const QSize &size, Mode mode, State state) const
#if QT_DEPRECATED_SINCE(6, 0)
/*!
\since 5.1
+ \deprecated [6.0] Use actualSize(size) instead.
Returns the actual size of the icon for the requested \a window \a size, \a
mode, and \a state.
@@ -1054,9 +1068,9 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state)
static QIconEngine *iconEngineFromSuffix(const QString &fileName, const QString &suffix)
{
if (!suffix.isEmpty()) {
- const int index = loader()->indexOf(suffix);
+ const int index = iceLoader()->indexOf(suffix);
if (index != -1) {
- if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
+ if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
return factory->create(fileName);
}
}
@@ -1138,10 +1152,9 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
Returns the name used to create the icon, if available.
Depending on the way the icon was created, it may have an associated
- name. This is the case for icons created with fromTheme() or icons
- using a QIconEngine which supports the QIconEngine::IconNameHook.
+ name. This is the case for icons created with fromTheme().
- \sa fromTheme(), QIconEngine
+ \sa fromTheme(), QIconEngine::iconName()
*/
QString QIcon::name() const
{
@@ -1154,6 +1167,10 @@ QString QIcon::name() const
\since 4.6
Sets the search paths for icon themes to \a paths.
+
+ The content of \a paths should follow the theme format
+ documented by setThemeName().
+
\sa themeSearchPaths(), fromTheme(), setThemeName()
*/
void QIcon::setThemeSearchPaths(const QStringList &paths)
@@ -1162,20 +1179,14 @@ void QIcon::setThemeSearchPaths(const QStringList &paths)
}
/*!
- \since 4.6
-
- Returns the search paths for icon themes.
-
- The default value will depend on the platform:
+ \since 4.6
- On X11, the search path will use the XDG_DATA_DIRS environment
- variable if available.
+ Returns the search paths for icon themes.
- By default all platforms will have the resource directory
- \c{:\icons} as a fallback. You can use "rcc -project" to generate a
- resource file from your icon theme.
+ The default search paths will be defined by the platform.
+ All platforms will also have the resource directory \c{:\icons} as a fallback.
- \sa setThemeSearchPaths(), fromTheme(), setThemeName()
+ \sa setThemeSearchPaths(), fromTheme(), setThemeName()
*/
QStringList QIcon::themeSearchPaths()
{
@@ -1187,7 +1198,13 @@ QStringList QIcon::themeSearchPaths()
Returns the fallback search paths for icons.
- The default value will depend on the platform.
+ The fallback search paths are consulted for standalone
+ icon files if the \l{themeName()}{current icon theme}
+ or \l{fallbackThemeName()}{fallback icon theme} do
+ not provide results for an icon lookup.
+
+ If not set, the fallback search paths will be defined
+ by the platform.
\sa setFallbackSearchPaths(), themeSearchPaths()
*/
@@ -1201,7 +1218,12 @@ QStringList QIcon::fallbackSearchPaths()
Sets the fallback search paths for icons to \a paths.
- \note To add some path without replacing existing ones:
+ The fallback search paths are consulted for standalone
+ icon files if the \l{themeName()}{current icon theme}
+ or \l{fallbackThemeName()}{fallback icon theme} do
+ not provide results for an icon lookup.
+
+ For example:
\snippet code/src_gui_image_qicon.cpp 5
@@ -1217,11 +1239,15 @@ void QIcon::setFallbackSearchPaths(const QStringList &paths)
Sets the current icon theme to \a name.
- The \a name should correspond to a directory name in the
- themeSearchPath() containing an index.theme
- file describing its contents.
+ The theme will be will be looked up in themeSearchPaths().
- \sa themeSearchPaths(), themeName()
+ At the moment the only supported icon theme format is the
+ \l{Freedesktop Icon Theme Specification}. The \a name should
+ correspond to a directory name in the themeSearchPath()
+ containing an \c index.theme file describing its contents.
+
+ \sa themeSearchPaths(), themeName(),
+ {Freedesktop Icon Theme Specification}
*/
void QIcon::setThemeName(const QString &name)
{
@@ -1233,8 +1259,12 @@ void QIcon::setThemeName(const QString &name)
Returns the name of the current icon theme.
- On X11, the current icon theme depends on your desktop
- settings. On other platforms it is not set by default.
+ If not set, the current icon theme will be defined by the
+ platform.
+
+ \note Platform icon themes are only implemented on
+ \l{Freedesktop} based systems at the moment, and the
+ icon theme depends on your desktop settings.
\sa setThemeName(), themeSearchPaths(), fromTheme(),
hasThemeIcon()
@@ -1249,8 +1279,12 @@ QString QIcon::themeName()
Returns the name of the fallback icon theme.
- On X11, if not set, the fallback icon theme depends on your desktop
- settings. On other platforms it is not set by default.
+ If not set, the fallback icon theme will be defined by the
+ platform.
+
+ \note Platform fallback icon themes are only implemented on
+ \l{Freedesktop} based systems at the moment, and the
+ icon theme depends on your desktop settings.
\sa setFallbackThemeName(), themeName()
*/
@@ -1264,12 +1298,16 @@ QString QIcon::fallbackThemeName()
Sets the fallback icon theme to \a name.
- The \a name should correspond to a directory name in the
- themeSearchPath() containing an index.theme
- file describing its contents.
+ The fallback icon theme is consulted for icons not provided by
+ the \l{themeName()}{current icon theme}, or if the \l{themeName()}
+ {current icon theme} does not exist.
+
+ The \a name should correspond to theme in the same format
+ as documented by setThemeName(), and will be looked up
+ in themeSearchPaths().
- \note This should be done before creating \l QGuiApplication, to ensure
- correct initialization.
+ \note Fallback icon themes should be set before creating
+ QGuiApplication, to ensure correct initialization.
\sa fallbackThemeName(), themeSearchPaths(), themeName()
*/
@@ -1281,67 +1319,63 @@ void QIcon::setFallbackThemeName(const QString &name)
/*!
\since 4.6
- Returns the QIcon corresponding to \a name in the current
- icon theme.
+ Returns the QIcon corresponding to \a name in the
+ \l{themeName()}{current icon theme}.
- The latest version of the freedesktop icon specification and naming
- specification can be obtained here:
-
- \list
- \li \l{http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html}
- \li \l{http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html}
- \endlist
+ If the current theme does not provide an icon for \a name,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
To fetch an icon from the current icon theme:
- \snippet code/src_gui_image_qicon.cpp 3
-
- \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}.
+ \snippet code/src_gui_image_qicon.cpp fromTheme
- \note If an icon can't be found in the current theme, then it will be
- searched in fallbackSearchPaths() as an unthemed icon.
+ If an \l{themeName()}{icon theme} has not been explicitly
+ set via setThemeName() a platform defined icon theme will
+ be used.
- \sa themeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths()
+ \sa themeName(), fallbackThemeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths(),
+ {Freedesktop Icon Naming Specification}
*/
QIcon QIcon::fromTheme(const QString &name)
{
- QIcon icon;
- if (qtIconCache()->contains(name)) {
- icon = *qtIconCache()->object(name);
- } else if (QDir::isAbsolutePath(name)) {
+ if (QIcon *cachedIcon = qtIconCache()->object(name))
+ return *cachedIcon;
+
+ if (QDir::isAbsolutePath(name))
return QIcon(name);
- } else {
- QPlatformTheme * const platformTheme = QGuiApplicationPrivate::platformTheme();
- bool hasUserTheme = QIconLoader::instance()->hasUserTheme();
- QIconEngine * const engine = (platformTheme && !hasUserTheme) ? platformTheme->createIconEngine(name)
- : new QIconLoaderEngine(name);
- QIcon *cachedIcon = new QIcon(engine);
- icon = *cachedIcon;
- qtIconCache()->insert(name, cachedIcon);
- }
+ QIcon icon(new QThemeIconEngine(name));
+ qtIconCache()->insert(name, new QIcon(icon));
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.
+ Returns the QIcon corresponding to \a name in the
+ \l{themeName()}{current icon theme}.
+
+ If the current theme does not provide an icon for \a name,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
+
+ If no icon is found \a fallback is returned.
- If you want to provide a guaranteed fallback for platforms that
- do not support theme icons, you can use the second argument:
+ This is useful to provide a guaranteed fallback, regardless of
+ whether the current set of icon themes and fallbacks paths
+ support the requested icon.
+
+ For example:
\snippet code/src_gui_image_qicon.cpp 4
+
+ \sa fallbackThemeName(), fallbackSearchPaths()
*/
QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
{
@@ -1357,7 +1391,8 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
\since 4.6
Returns \c true if there is an icon available for \a name in the
- current icon theme, otherwise returns \c false.
+ current icon theme or any of the fallbacks, as described by
+ fromTheme(), otherwise returns \c false.
\sa themeSearchPaths(), fromTheme(), setThemeName()
*/
@@ -1368,6 +1403,401 @@ bool QIcon::hasThemeIcon(const QString &name)
return icon.name() == name;
}
+static constexpr auto themeIconMapping = qOffsetStringArray(
+ "address-book-new",
+ "application-exit",
+ "appointment-new",
+ "call-start",
+ "call-stop",
+ "contact-new",
+ "document-new",
+ "document-open",
+ "document-open-recent",
+ "document-page-setup",
+ "document-print",
+ "document-print-preview",
+ "document-properties",
+ "document-revert",
+ "document-save",
+ "document-save-as",
+ "document-send",
+ "edit-clear",
+ "edit-copy",
+ "edit-cut",
+ "edit-delete",
+ "edit-find",
+ "edit-paste",
+ "edit-redo",
+ "edit-select-all",
+ "edit-undo",
+ "folder-new",
+ "format-indent-less",
+ "format-indent-more",
+ "format-justify-center",
+ "format-justify-fill",
+ "format-justify-left",
+ "format-justify-right",
+ "format-text-direction-ltr",
+ "format-text-direction-rtl",
+ "format-text-bold",
+ "format-text-italic",
+ "format-text-underline",
+ "format-text-strikethrough",
+ "go-down",
+ "go-home",
+ "go-next",
+ "go-previous",
+ "go-up",
+ "help-about",
+ "help-faq",
+ "insert-image",
+ "insert-link",
+ "insert-text",
+ "list-add",
+ "list-remove",
+ "mail-forward",
+ "mail-mark-important",
+ "mail-mark-read",
+ "mail-mark-unread",
+ "mail-message-new",
+ "mail-reply-all",
+ "mail-reply-sender",
+ "mail-send",
+ "media-eject",
+ "media-playback-pause",
+ "media-playback-start",
+ "media-playback-stop",
+ "media-record",
+ "media-seek-backward",
+ "media-seek-forward",
+ "media-skip-backward",
+ "media-skip-forward",
+ "object-rotate-left",
+ "object-rotate-right",
+ "process-stop",
+ "system-lock-screen",
+ "system-log-out",
+ "system-search",
+ "system-reboot",
+ "system-shutdown",
+ "tools-check-spelling",
+ "view-fullscreen",
+ "view-refresh",
+ "view-restore",
+ "window-close",
+ "window-new",
+ "zoom-fit-best",
+ "zoom-in",
+ "zoom-out",
+
+ "audio-card",
+ "audio-input-microphone",
+ "battery",
+ "camera-photo",
+ "camera-video",
+ "camera-web",
+ "computer",
+ "drive-harddisk",
+ "drive-optical",
+ "input-gaming",
+ "input-keyboard",
+ "input-mouse",
+ "input-tablet",
+ "media-flash",
+ "media-optical",
+ "media-tape",
+ "multimedia-player",
+ "network-wired",
+ "network-wireless",
+ "phone",
+ "printer",
+ "scanner",
+ "video-display",
+
+ "appointment-missed",
+ "appointment-soon",
+ "audio-volume-high",
+ "audio-volume-low",
+ "audio-volume-medium",
+ "audio-volume-muted",
+ "battery-caution",
+ "battery-low",
+ "dialog-error",
+ "dialog-information",
+ "dialog-password",
+ "dialog-question",
+ "dialog-warning",
+ "folder-drag-accept",
+ "folder-open",
+ "folder-visiting",
+ "image-loading",
+ "image-missing",
+ "mail-attachment",
+ "mail-unread",
+ "mail-read",
+ "mail-replied",
+ "media-playlist-repeat",
+ "media-playlist-shuffle",
+ "network-offline",
+ "printer-printing",
+ "security-high",
+ "security-low",
+ "software-update-available",
+ "software-update-urgent",
+ "sync-error",
+ "sync-synchronizing",
+ "user-available",
+ "user-offline",
+ "weather-clear",
+ "weather-clear-night",
+ "weather-few-clouds",
+ "weather-few-clouds-night",
+ "weather-fog",
+ "weather-showers",
+ "weather-snow",
+ "weather-storm"
+);
+static_assert(QIcon::ThemeIcon::NThemeIcons == QIcon::ThemeIcon(themeIconMapping.count()));
+
+static constexpr QLatin1StringView themeIconName(QIcon::ThemeIcon icon)
+{
+ using ThemeIconIndex = std::underlying_type_t<QIcon::ThemeIcon>;
+ const auto index = static_cast<ThemeIconIndex>(icon);
+ Q_ASSERT(index < themeIconMapping.count());
+ return QLatin1StringView(themeIconMapping.viewAt(index));
+}
+
+/*!
+ \enum QIcon::ThemeIcon
+ \since 6.7
+
+ This enum provides access to icons that are provided by most
+ icon theme implementations.
+
+ \value AddressBookNew The icon for the action to create a new address book.
+ \value ApplicationExit The icon for exiting an application.
+ \value AppointmentNew The icon for the action to create a new appointment.
+ \value CallStart The icon for initiating or accepting a call.
+ \value CallStop The icon for stopping a current call.
+ \value ContactNew The icon for the action to create a new contact.
+ \value DocumentNew The icon for the action to create a new document.
+ \value DocumentOpen The icon for the action to open a document.
+ \value DocumentOpenRecent The icon for the action to open a document that was recently opened.
+ \value DocumentPageSetup The icon for the \e{page setup} action.
+ \value DocumentPrint The icon for the \e{print} action.
+ \value DocumentPrintPreview The icon for the \e{print preview} action.
+ \value DocumentProperties The icon for the action to view the properties of a document.
+ \value DocumentRevert The icon for the action of reverting to a previous version of a document.
+ \value DocumentSave The icon for the \e{save} action.
+ \value DocumentSaveAs The icon for the \e{save as} action.
+ \value DocumentSend The icon for the \e{send} action.
+ \value EditClear The icon for the \e{clear} action.
+ \value EditCopy The icon for the \e{copy} action.
+ \value EditCut The icon for the \e{cut} action.
+ \value EditDelete The icon for the \e{delete} action.
+ \value EditFind The icon for the \e{find} action.
+ \value EditPaste The icon for the \e{paste} action.
+ \value EditRedo The icon for the \e{redo} action.
+ \value EditSelectAll The icon for the \e{select all} action.
+ \value EditUndo The icon for the \e{undo} action.
+ \value FolderNew The icon for creating a new folder.
+ \value FormatIndentLess The icon for the \e{decrease indent formatting} action.
+ \value FormatIndentMore The icon for the \e{increase indent formatting} action.
+ \value FormatJustifyCenter The icon for the \e{center justification formatting} action.
+ \value FormatJustifyFill The icon for the \e{fill justification formatting} action.
+ \value FormatJustifyLeft The icon for the \e{left justification formatting} action.
+ \value FormatJustifyRight The icon for the \e{right justification} action.
+ \value FormatTextDirectionLtr The icon for the \e{left-to-right text formatting} action.
+ \value FormatTextDirectionRtl The icon for the \e{right-to-left formatting} action.
+ \value FormatTextBold The icon for the \e{bold text formatting} action.
+ \value FormatTextItalic The icon for the \e{italic text formatting} action.
+ \value FormatTextUnderline The icon for the \e{underlined text formatting} action.
+ \value FormatTextStrikethrough The icon for the \e{strikethrough text formatting} action.
+ \value GoDown The icon for the \e{go down in a list} action.
+ \value GoHome The icon for the \e{go to home location} action.
+ \value GoNext The icon for the \e{go to the next item in a list} action.
+ \value GoPrevious The icon for the \e{go to the previous item in a list} action.
+ \value GoUp The icon for the \e{go up in a list} action.
+ \value HelpAbout The icon for the \e{About} item in the Help menu.
+ \value HelpFaq The icon for the \e{FAQ} item in the Help menu.
+ \value InsertImage The icon for the \e{insert image} action of an application.
+ \value InsertLink The icon for the \e{insert link} action of an application.
+ \value InsertText The icon for the \e{insert text} action of an application.
+ \value ListAdd The icon for the \e{add to list} action.
+ \value ListRemove The icon for the \e{remove from list} action.
+ \value MailForward The icon for the \e{forward} action.
+ \value MailMarkImportant The icon for the \e{mark as important} action.
+ \value MailMarkRead The icon for the \e{mark as read} action.
+ \value MailMarkUnread The icon for the \e{mark as unread} action.
+ \value MailMessageNew The icon for the \e{compose new mail} action.
+ \value MailReplyAll The icon for the \e{reply to all} action.
+ \value MailReplySender The icon for the \e{reply to sender} action.
+ \value MailSend The icon for the \e{send} action.
+ \value MediaEject The icon for the \e{eject} action of a media player or file manager.
+ \value MediaPlaybackPause The icon for the \e{pause} action of a media player.
+ \value MediaPlaybackStart The icon for the \e{start playback} action of a media player.
+ \value MediaPlaybackStop The icon for the \e{stop} action of a media player.
+ \value MediaRecord The icon for the \e{record} action of a media application.
+ \value MediaSeekBackward The icon for the \e{seek backward} action of a media player.
+ \value MediaSeekForward The icon for the \e{seek forward} action of a media player.
+ \value MediaSkipBackward The icon for the \e{skip backward} action of a media player.
+ \value MediaSkipForward The icon for the \e{skip forward} action of a media player.
+ \value ObjectRotateLeft The icon for the \e{rotate left} action performed on an object.
+ \value ObjectRotateRight The icon for the \e{rotate right} action performed on an object.
+ \value ProcessStop The icon for the \e{stop action in applications with} actions that
+ may take a while to process, such as web page loading in a browser.
+ \value SystemLockScreen The icon for the \e{lock screen} action.
+ \value SystemLogOut The icon for the \e{log out} action.
+ \value SystemSearch The icon for the \e{search} action.
+ \value SystemReboot The icon for the \e{reboot} action.
+ \value SystemShutdown The icon for the \e{shutdown} action.
+ \value ToolsCheckSpelling The icon for the \e{check spelling} action.
+ \value ViewFullscreen The icon for the \e{fullscreen} action.
+ \value ViewRefresh The icon for the \e{refresh} action.
+ \value ViewRestore The icon for leaving the fullscreen view.
+ \value WindowClose The icon for the \e{close window} action.
+ \value WindowNew The icon for the \e{new window} action.
+ \value ZoomFitBest The icon for the \e{best fit} action.
+ \value ZoomIn The icon for the \e{zoom in} action.
+ \value ZoomOut The icon for the \e{zoom out} action.
+
+ \value AudioCard The icon for the audio rendering device.
+ \value AudioInputMicrophone The icon for the microphone audio input device.
+ \value Battery The icon for the system battery device.
+ \value CameraPhoto The icon for a digital still camera devices.
+ \value CameraVideo The icon for a video camera device.
+ \value CameraWeb The icon for a web camera device.
+ \value Computer The icon for the computing device as a whole.
+ \value DriveHarddisk The icon for hard disk drives.
+ \value DriveOptical The icon for optical media drives such as CD and DVD.
+ \value InputGaming The icon for the gaming input device.
+ \value InputKeyboard The icon for the keyboard input device.
+ \value InputMouse The icon for the mousing input device.
+ \value InputTablet The icon for graphics tablet input devices.
+ \value MediaFlash The icon for flash media, such as a memory stick.
+ \value MediaOptical The icon for physical optical media such as CD and DVD.
+ \value MediaTape The icon for generic physical tape media.
+ \value MultimediaPlayer The icon for generic multimedia playing devices.
+ \value NetworkWired The icon for wired network connections.
+ \value NetworkWireless The icon for wireless network connections.
+ \value Phone The icon for phone devices.
+ \value Printer The icon for a printer device.
+ \value Scanner The icon for a scanner device.
+ \value VideoDisplay The icon for the monitor that video gets displayed on.
+
+ \value AppointmentMissed The icon for when an appointment was missed.
+ \value AppointmentSoon The icon for when an appointment will occur soon.
+ \value AudioVolumeHigh The icon used to indicate high audio volume.
+ \value AudioVolumeLow The icon used to indicate low audio volume.
+ \value AudioVolumeMedium The icon used to indicate medium audio volume.
+ \value AudioVolumeMuted The icon used to indicate the muted state for audio playback.
+ \value BatteryCaution The icon used when the battery is below 40%.
+ \value BatteryLow The icon used when the battery is below 20%.
+ \value DialogError The icon used when a dialog is opened to explain an error
+ condition to the user.
+ \value DialogInformation The icon used when a dialog is opened to give information to the
+ user that may be pertinent to the requested action.
+ \value DialogPassword The icon used when a dialog requesting the authentication
+ credentials for a user is opened.
+ \value DialogQuestion The icon used when a dialog is opened to ask a simple question
+ to the user.
+ \value DialogWarning The icon used when a dialog is opened to warn the user of
+ impending issues with the requested action.
+ \value FolderDragAccept The icon used for a folder while an acceptable object is being
+ dragged onto it.
+ \value FolderOpen The icon used for folders, while their contents are being displayed
+ within the same window.
+ \value FolderVisiting The icon used for folders, while their contents are being displayed
+ in another window.
+ \value ImageLoading The icon used while another image is being loaded.
+ \value ImageMissing The icon used when another image could not be loaded.
+ \value MailAttachment The icon for a message that contains attachments.
+ \value MailUnread The icon for an unread message.
+ \value MailRead The icon for a read message.
+ \value MailReplied The icon for a message that has been replied to.
+ \value MediaPlaylistRepeat The icon for the repeat mode of a media player.
+ \value MediaPlaylistShuffle The icon for the shuffle mode of a media player.
+ \value NetworkOffline The icon used to indicate that the device is not connected to the
+ network.
+ \value PrinterPrinting The icon used while a print job is successfully being spooled to a
+ printing device.
+ \value SecurityHigh The icon used to indicate that the security level of an item is
+ known to be high.
+ \value SecurityLow The icon used to indicate that the security level of an item is
+ known to be low.
+ \value SoftwareUpdateAvailable The icon used to indicate that an update is available.
+ \value SoftwareUpdateUrgent The icon used to indicate that an urgent update is available.
+ \value SyncError The icon used when an error occurs while attempting to synchronize
+ data across devices.
+ \value SyncSynchronizing The icon used while data is successfully synchronizing across
+ devices.
+ \value UserAvailable The icon used to indicate that a user is available.
+ \value UserOffline The icon used to indicate that a user is not available.
+ \value WeatherClear The icon used to indicate that the sky is clear.
+ \value WeatherClearNight The icon used to indicate that the sky is clear
+ during the night.
+ \value WeatherFewClouds The icon used to indicate that the sky is partly cloudy.
+ \value WeatherFewCloudsNight The icon used to indicate that the sky is partly cloudy
+ during the night.
+ \value WeatherFog The icon used to indicate that the weather is foggy.
+ \value WeatherShowers The icon used to indicate that rain showers are occurring.
+ \value WeatherSnow The icon used to indicate that snow is falling.
+ \value WeatherStorm The icon used to indicate that the weather is stormy.
+
+ \omitvalue NThemeIcons
+
+ \sa {QIcon#Creating an icon from a theme or icon library},
+ fromTheme()
+*/
+
+/*!
+ \since 6.7
+ \overload
+
+ Returns \c true if there is an icon available for \a icon in the
+ current icon theme or any of the fallbacks, as described by
+ fromTheme(), otherwise returns \c false.
+
+ \sa fromTheme()
+*/
+bool QIcon::hasThemeIcon(QIcon::ThemeIcon icon)
+{
+ return hasThemeIcon(themeIconName(icon));
+}
+
+/*!
+ \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon)
+ \fn QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback)
+ \since 6.7
+ \overload
+
+ Returns the QIcon corresponding to \a icon in the
+ \l{themeName()}{current icon theme}.
+
+ If the current theme does not provide an icon for \a icon,
+ the \l{fallbackThemeName()}{fallback icon theme} is consulted,
+ before falling back to looking up standalone icon files in the
+ \l{QIcon::fallbackSearchPaths()}{fallback icon search path}.
+ Finally, the platform's native icon library is consulted.
+
+ If no icon is found and a \a fallback is provided, \a fallback is
+ returned. This is useful to provide a guaranteed fallback, regardless
+ of whether the current set of icon themes and fallbacks paths
+ support the requested icon.
+
+ If no icon is found and no \a fallback is provided, a default
+ constructed, empty QIcon is returned.
+*/
+QIcon QIcon::fromTheme(QIcon::ThemeIcon icon)
+{
+ return fromTheme(themeIconName(icon));
+}
+
+QIcon QIcon::fromTheme(QIcon::ThemeIcon icon, const QIcon &fallback)
+{
+ return fromTheme(themeIconName(icon), fallback);
+}
+
/*!
\since 5.6
@@ -1377,10 +1807,9 @@ bool QIcon::hasThemeIcon(const QString &name)
*/
void QIcon::setIsMask(bool isMask)
{
+ detach();
if (!d)
d = new QIconPrivate(new QPixmapIconEngine);
- else
- detach();
d->is_mask = isMask;
}
@@ -1460,16 +1889,16 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon)
icon = QIcon();
QString key;
s >> key;
- if (key == QLatin1String("QPixmapIconEngine")) {
+ if (key == "QPixmapIconEngine"_L1) {
icon.d = new QIconPrivate(new QPixmapIconEngine);
icon.d->engine->read(s);
- } else if (key == QLatin1String("QIconLoaderEngine")) {
- icon.d = new QIconPrivate(new QIconLoaderEngine());
+ } else if (key == "QIconLoaderEngine"_L1 || key == "QThemeIconEngine"_L1) {
+ icon.d = new QIconPrivate(new QThemeIconEngine);
icon.d->engine->read(s);
} else {
- const int index = loader()->indexOf(key);
+ const int index = iceLoader()->indexOf(key);
if (index != -1) {
- if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) {
+ if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(iceLoader()->instance(index))) {
if (QIconEngine *engine= factory->create()) {
icon.d = new QIconPrivate(engine);
engine->read(s);
@@ -1560,17 +1989,17 @@ QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRati
if (disableNxImageLoading)
return baseFileName;
- int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.'));
+ int dotIndex = baseFileName.lastIndexOf(u'.');
if (dotIndex == -1) { /* no dot */
dotIndex = baseFileName.size(); /* append */
- } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == QLatin1Char('9')
- && baseFileName[dotIndex - 2] == QLatin1Char('.')) {
+ } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == u'9'
+ && baseFileName[dotIndex - 2] == u'.') {
// If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it.
dotIndex -= 2;
}
QString atNxfileName = baseFileName;
- atNxfileName.insert(dotIndex, QLatin1String("@2x"));
+ atNxfileName.insert(dotIndex, "@2x"_L1);
// Check for @Nx, ..., @3x, @2x file versions,
for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) {
atNxfileName[dotIndex + 1] = QLatin1Char('0' + n);
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index fab8c3fe21..5100ada548 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICON_H
#define QICON_H
@@ -58,11 +22,168 @@ public:
enum Mode { Normal, Disabled, Active, Selected };
enum State { On, Off };
+ enum class ThemeIcon {
+ AddressBookNew,
+ ApplicationExit,
+ AppointmentNew,
+ CallStart,
+ CallStop,
+ ContactNew,
+ DocumentNew,
+ DocumentOpen,
+ DocumentOpenRecent,
+ DocumentPageSetup,
+ DocumentPrint,
+ DocumentPrintPreview,
+ DocumentProperties,
+ DocumentRevert,
+ DocumentSave,
+ DocumentSaveAs,
+ DocumentSend,
+ EditClear,
+ EditCopy,
+ EditCut,
+ EditDelete,
+ EditFind,
+ EditPaste,
+ EditRedo,
+ EditSelectAll,
+ EditUndo,
+ FolderNew,
+ FormatIndentLess,
+ FormatIndentMore,
+ FormatJustifyCenter,
+ FormatJustifyFill,
+ FormatJustifyLeft,
+ FormatJustifyRight,
+ FormatTextDirectionLtr,
+ FormatTextDirectionRtl,
+ FormatTextBold,
+ FormatTextItalic,
+ FormatTextUnderline,
+ FormatTextStrikethrough,
+ GoDown,
+ GoHome,
+ GoNext,
+ GoPrevious,
+ GoUp,
+ HelpAbout,
+ HelpFaq,
+ InsertImage,
+ InsertLink,
+ InsertText,
+ ListAdd,
+ ListRemove,
+ MailForward,
+ MailMarkImportant,
+ MailMarkRead,
+ MailMarkUnread,
+ MailMessageNew,
+ MailReplyAll,
+ MailReplySender,
+ MailSend,
+ MediaEject,
+ MediaPlaybackPause,
+ MediaPlaybackStart,
+ MediaPlaybackStop,
+ MediaRecord,
+ MediaSeekBackward,
+ MediaSeekForward,
+ MediaSkipBackward,
+ MediaSkipForward,
+ ObjectRotateLeft,
+ ObjectRotateRight,
+ ProcessStop,
+ SystemLockScreen,
+ SystemLogOut,
+ SystemSearch,
+ SystemReboot,
+ SystemShutdown,
+ ToolsCheckSpelling,
+ ViewFullscreen,
+ ViewRefresh,
+ ViewRestore,
+ WindowClose,
+ WindowNew,
+ ZoomFitBest,
+ ZoomIn,
+ ZoomOut,
+
+ AudioCard,
+ AudioInputMicrophone,
+ Battery,
+ CameraPhoto,
+ CameraVideo,
+ CameraWeb,
+ Computer,
+ DriveHarddisk,
+ DriveOptical,
+ InputGaming,
+ InputKeyboard,
+ InputMouse,
+ InputTablet,
+ MediaFlash,
+ MediaOptical,
+ MediaTape,
+ MultimediaPlayer,
+ NetworkWired,
+ NetworkWireless,
+ Phone,
+ Printer,
+ Scanner,
+ VideoDisplay,
+
+ AppointmentMissed,
+ AppointmentSoon,
+ AudioVolumeHigh,
+ AudioVolumeLow,
+ AudioVolumeMedium,
+ AudioVolumeMuted,
+ BatteryCaution,
+ BatteryLow,
+ DialogError,
+ DialogInformation,
+ DialogPassword,
+ DialogQuestion,
+ DialogWarning,
+ FolderDragAccept,
+ FolderOpen,
+ FolderVisiting,
+ ImageLoading,
+ ImageMissing,
+ MailAttachment,
+ MailUnread,
+ MailRead,
+ MailReplied,
+ MediaPlaylistRepeat,
+ MediaPlaylistShuffle,
+ NetworkOffline,
+ PrinterPrinting,
+ SecurityHigh,
+ SecurityLow,
+ SoftwareUpdateAvailable,
+ SoftwareUpdateUrgent,
+ SyncError,
+ SyncSynchronizing,
+ UserAvailable,
+ UserOffline,
+ WeatherClear,
+ WeatherClearNight,
+ WeatherFewClouds,
+ WeatherFewCloudsNight,
+ WeatherFog,
+ WeatherShowers,
+ WeatherSnow,
+ WeatherStorm,
+
+ NThemeIcons
+ };
+
QIcon() noexcept;
QIcon(const QPixmap &pixmap);
QIcon(const QIcon &other);
QIcon(QIcon &&other) noexcept
- : d(qExchange(other.d, nullptr))
+ : d(std::exchange(other.d, nullptr))
{}
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
@@ -70,7 +191,7 @@ public:
QIcon &operator=(const QIcon &other);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QIcon)
inline void swap(QIcon &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
bool operator==(const QIcon &) const = delete;
bool operator!=(const QIcon &) const = delete;
@@ -117,6 +238,10 @@ public:
static QIcon fromTheme(const QString &name, const QIcon &fallback);
static bool hasThemeIcon(const QString &name);
+ static QIcon fromTheme(ThemeIcon icon);
+ static QIcon fromTheme(ThemeIcon icon, const QIcon &fallback);
+ static bool hasThemeIcon(ThemeIcon icon);
+
static QStringList themeSearchPaths();
static void setThemeSearchPaths(const QStringList &searchpath);
@@ -129,8 +254,6 @@ public:
static QString fallbackThemeName();
static void setFallbackThemeName(const QString &name);
- Q_DUMMY_COMPARISON_OPERATOR(QIcon)
-
private:
QIconPrivate *d;
#if !defined(QT_NO_DATASTREAM)
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index 40cb0c7efa..c5bf120620 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICON_P_H
#define QICON_P_H
@@ -78,6 +42,8 @@ public:
int serialNum;
int detach_no;
bool is_mask;
+
+ static void clearIconCache();
};
@@ -97,7 +63,7 @@ struct QPixmapIconEngineEntry
QIcon::State state;
bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
};
-Q_DECLARE_TYPEINFO(QPixmapIconEngineEntry, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QPixmapIconEngineEntry, Q_RELOCATABLE_TYPE);
inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
: fileName(file), size(image.size()), scale(image.devicePixelRatio()), mode(m), state(s)
@@ -118,7 +84,7 @@ public:
QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) override;
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override;
-
+ bool isNull() override;
QString key() const override;
QIconEngine *clone() const override;
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index f1004b4d2a..78273bdeb3 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -1,43 +1,8 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qiconengine.h"
+#include "qiconengine_p.h"
#include "qpainter.h"
QT_BEGIN_NAMESPACE
@@ -160,8 +125,8 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
was added in Qt 5.7.
\value ScaledPixmapHook Provides a way to get a pixmap that is scaled
- according to the given scale (typically equal to the \l {Glossary Of High
- DPI Terms}{device pixel ratio}). The \a data argument of the virtual_hook()
+ according to the given scale (typically equal to the \l {High
+ DPI}{device pixel ratio}). The \a data argument of the virtual_hook()
function is a \l ScaledPixmapArgument pointer that contains both the input and
output arguments. This enum value was added in Qt 5.9.
@@ -178,8 +143,8 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
the \a id parameter is QIconEngine::ScaledPixmapHook.
The struct provides a way for icons created via \l QIcon::fromTheme()
- to return pixmaps that are designed for the current \l {Glossary Of High
- DPI Terms}{device pixel ratio}. The scale for such an icon is specified
+ to return pixmaps that are designed for the current \l {High
+ DPI}{device pixel ratio}. The scale for such an icon is specified
using the \l {Icon Theme Specification - Directory Layout}{Scale directory key}
in the appropriate \c index.theme file.
@@ -323,8 +288,8 @@ bool QIconEngine::isNull()
Returns a pixmap for the given \a size, \a mode, \a state and \a scale.
- The \a scale argument is typically equal to the \l {Glossary Of High DPI
- Terms}{device pixel ratio} of the display.
+ The \a scale argument is typically equal to the \l {High DPI}
+ {device pixel ratio} of the display.
\include qiconengine-virtualhookhelper.qdocinc
@@ -343,4 +308,78 @@ QPixmap QIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::St
return arg.pixmap;
}
+
+// ------- QProxyIconEngine -----
+
+void QProxyIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->paint(painter, rect, mode, state);
+}
+
+QSize QProxyIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->actualSize(size, mode, state);
+}
+
+QPixmap QProxyIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->pixmap(size, mode, state);
+}
+
+void QProxyIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->addPixmap(pixmap, mode, state);
+}
+
+void QProxyIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
+{
+ proxiedEngine()->addFile(fileName, size, mode, state);
+}
+
+QString QProxyIconEngine::key() const
+{
+ return proxiedEngine()->key();
+}
+
+QIconEngine *QProxyIconEngine::clone() const
+{
+ return proxiedEngine()->clone();
+}
+
+bool QProxyIconEngine::read(QDataStream &in)
+{
+ return proxiedEngine()->read(in);
+}
+
+bool QProxyIconEngine::write(QDataStream &out) const
+{
+ return proxiedEngine()->write(out);
+}
+
+QList<QSize> QProxyIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
+{
+ return proxiedEngine()->availableSizes(mode, state);
+}
+
+QString QProxyIconEngine::iconName()
+{
+ return proxiedEngine()->iconName();
+}
+
+bool QProxyIconEngine::isNull()
+{
+ return proxiedEngine()->isNull();
+}
+
+QPixmap QProxyIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
+{
+ return proxiedEngine()->scaledPixmap(size, mode, state, scale);
+}
+
+void QProxyIconEngine::virtual_hook(int id, void *data)
+{
+ proxiedEngine()->virtual_hook(id, data);
+}
+
+
QT_END_NAMESPACE
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 383e116f43..61411b0660 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONENGINE_H
#define QICONENGINE_H
diff --git a/src/gui/image/qiconengine_p.h b/src/gui/image/qiconengine_p.h
new file mode 100644
index 0000000000..3cf0998429
--- /dev/null
+++ b/src/gui/image/qiconengine_p.h
@@ -0,0 +1,59 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QICONENGINE_P_H
+#define QICONENGINE_P_H
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#ifndef QT_NO_ICON
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/QIcon>
+#include <QtGui/QIconEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QIconEngine;
+
+class QProxyIconEngine : public QIconEngine
+{
+public:
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+ QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+
+ void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) override;
+ void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+
+ QString key() const override;
+ QIconEngine *clone() const override;
+ bool read(QDataStream &in) override;
+ bool write(QDataStream &out) const override;
+
+ QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal,
+ QIcon::State state = QIcon::Off) override;
+
+ QString iconName() override;
+ bool isNull() override;
+ QPixmap scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override;
+
+ void virtual_hook(int id, void *data) override;
+protected:
+ virtual QIconEngine *proxiedEngine() const = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ICON
+
+#endif // QICONENGINE_P_H
diff --git a/src/gui/image/qiconengineplugin.cpp b/src/gui/image/qiconengineplugin.cpp
index ca80ee50a7..f75b5370f1 100644
--- a/src/gui/image/qiconengineplugin.cpp
+++ b/src/gui/image/qiconengineplugin.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qiconengineplugin.h"
#include "qiconengine.h"
@@ -97,3 +61,5 @@ QIconEnginePlugin::~QIconEnginePlugin()
QT_END_NAMESPACE
+
+#include "moc_qiconengineplugin.cpp"
diff --git a/src/gui/image/qiconengineplugin.h b/src/gui/image/qiconengineplugin.h
index f2a1c0107a..b005baff0b 100644
--- a/src/gui/image/qiconengineplugin.h
+++ b/src/gui/image/qiconengineplugin.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONENGINEPLUGIN_H
#define QICONENGINEPLUGIN_H
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index e5aa7cd0ac..982b9a26b4 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QT_NO_ICON
#include <private/qiconloader_p.h>
@@ -50,6 +14,7 @@
#include <QtCore/qmath.h>
#include <QtCore/QList>
#include <QtCore/QDir>
+#include <QtCore/qloggingcategory.h>
#if QT_CONFIG(settings)
#include <QtCore/QSettings>
#endif
@@ -59,6 +24,10 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcIconLoader, "qt.gui.icon.loader")
+
+using namespace Qt::StringLiterals;
+
Q_GLOBAL_STATIC(QIconLoader, iconLoaderInstance)
/* Theme to use in last resort, if the theme does not have the icon, neither the parents */
@@ -122,8 +91,11 @@ void QIconLoader::ensureInitialized()
if (m_systemTheme.isEmpty())
m_systemTheme = systemFallbackThemeName();
- if (qt_iconEngineFactoryLoader()->keyMap().key(QLatin1String("svg"), -1) != -1)
+ if (qt_iconEngineFactoryLoader()->keyMap().key("svg"_L1, -1) != -1)
m_supportsSvg = true;
+
+ qCDebug(lcIconLoader) << "Initialized icon loader with system theme"
+ << m_systemTheme << "and SVG support" << m_supportsSvg;
}
}
@@ -135,7 +107,7 @@ void QIconLoader::ensureInitialized()
created, to avoid a race condition (QTBUG-74252). When this function is
called from there, ensureInitialized() does not succeed because there
is no QPlatformTheme yet, so systemThemeName() is empty, and we don't want
- m_systemTheme to get intialized to the fallback theme instead of the normal one.
+ m_systemTheme to get initialized to the fallback theme instead of the normal one.
*/
QIconLoader *QIconLoader::instance()
{
@@ -147,21 +119,45 @@ QIconLoader *QIconLoader::instance()
// icons if the theme has changed.
void QIconLoader::updateSystemTheme()
{
- // Only change if this is not explicitly set by the user
- if (m_userTheme.isEmpty()) {
- QString theme = systemThemeName();
- if (theme.isEmpty())
- theme = fallbackThemeName();
- if (theme != m_systemTheme) {
- m_systemTheme = theme;
- invalidateKey();
- }
- }
+ const QString currentSystemTheme = m_systemTheme;
+ m_systemTheme = systemThemeName();
+ if (m_systemTheme.isEmpty())
+ m_systemTheme = systemFallbackThemeName();
+ if (m_systemTheme != currentSystemTheme)
+ qCDebug(lcIconLoader) << "Updated system theme to" << m_systemTheme;
+ // Invalidate even if the system theme name hasn't changed, as the
+ // theme itself may have changed its underlying icon lookup logic.
+ if (!hasUserTheme())
+ invalidateKey();
+}
+
+void QIconLoader::invalidateKey()
+{
+ // Invalidating the key here will result in QThemeIconEngine
+ // recreating the actual engine the next time the icon is used.
+ // We don't need to clear the QIcon cache itself.
+ m_themeKey++;
+}
+
+QString QIconLoader::themeName() const
+{
+ return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme;
}
void QIconLoader::setThemeName(const QString &themeName)
{
+ if (m_userTheme == themeName)
+ return;
+
+ qCDebug(lcIconLoader) << "Setting user theme name to" << themeName;
+
+ const bool hadUserTheme = hasUserTheme();
m_userTheme = themeName;
+ // if we cleared the user theme, then reset search paths as well,
+ // otherwise we'll keep looking in the user-defined search paths for
+ // a system-provide theme, which will never work.
+ if (!hasUserTheme() && hadUserTheme)
+ setThemeSearchPath(systemIconSearchPaths());
invalidateKey();
}
@@ -172,11 +168,14 @@ QString QIconLoader::fallbackThemeName() const
void QIconLoader::setFallbackThemeName(const QString &themeName)
{
+ qCDebug(lcIconLoader) << "Setting fallback theme name to" << themeName;
m_userFallbackTheme = themeName;
+ invalidateKey();
}
void QIconLoader::setThemeSearchPath(const QStringList &searchPaths)
{
+ qCDebug(lcIconLoader) << "Setting theme search path to" << searchPaths;
m_iconDirs = searchPaths;
themeList.clear();
invalidateKey();
@@ -187,13 +186,14 @@ QStringList QIconLoader::themeSearchPaths() const
if (m_iconDirs.isEmpty()) {
m_iconDirs = systemIconSearchPaths();
// Always add resource directory as search path
- m_iconDirs.append(QLatin1String(":/icons"));
+ m_iconDirs.append(":/icons"_L1);
}
return m_iconDirs;
}
void QIconLoader::setFallbackSearchPaths(const QStringList &searchPaths)
{
+ qCDebug(lcIconLoader) << "Setting fallback search path to" << searchPaths;
m_fallbackDirs = searchPaths;
invalidateKey();
}
@@ -248,8 +248,8 @@ private:
QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName)
: m_isValid(false)
{
- QFileInfo info(dirName + QLatin1String("/icon-theme.cache"));
- if (!info.exists() || info.lastModified() < QFileInfo(dirName).lastModified())
+ QFileInfo info(dirName + "/icon-theme.cache"_L1);
+ if (!info.exists() || info.lastModified(QTimeZone::UTC) < QFileInfo(dirName).lastModified(QTimeZone::UTC))
return;
m_file.setFileName(info.absoluteFilePath());
if (!m_file.open(QFile::ReadOnly))
@@ -264,13 +264,13 @@ QIconCacheGtkReader::QIconCacheGtkReader(const QString &dirName)
m_isValid = true;
// Check that all the directories are older than the cache
- auto lastModified = info.lastModified();
+ const QDateTime lastModified = info.lastModified(QTimeZone::UTC);
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()) {
+ if (!m_isValid || offset >= m_size || lastModified < QFileInfo(dirName + u'/'
+ + QString::fromUtf8(reinterpret_cast<const char*>(m_data + offset))).lastModified(QTimeZone::UTC)) {
m_isValid = false;
return;
}
@@ -348,7 +348,7 @@ QIconTheme::QIconTheme(const QString &themeName)
const QStringList iconDirs = QIcon::themeSearchPaths();
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
- QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
+ QString themeDir = iconDir.path() + u'/' + themeName;
QFileInfo themeDirInfo(themeDir);
if (themeDirInfo.isDir()) {
@@ -357,77 +357,96 @@ QIconTheme::QIconTheme(const QString &themeName)
}
if (!m_valid) {
- themeIndex.setFileName(themeDir + QLatin1String("/index.theme"));
- if (themeIndex.exists())
- m_valid = true;
+ themeIndex.setFileName(themeDir + "/index.theme"_L1);
+ m_valid = themeIndex.exists();
+ qCDebug(lcIconLoader) << "Probing theme file at" << themeIndex.fileName() << m_valid;
}
}
#if QT_CONFIG(settings)
- if (themeIndex.exists()) {
+ if (m_valid) {
const QSettings indexReader(themeIndex.fileName(), QSettings::IniFormat);
const QStringList keys = indexReader.allKeys();
for (const QString &key : keys) {
- if (key.endsWith(QLatin1String("/Size"))) {
+ if (key.endsWith("/Size"_L1)) {
// Note the QSettings ini-format does not accept
// slashes in key names, hence we have to cheat
if (int size = indexReader.value(key).toInt()) {
QString directoryKey = key.left(key.size() - 5);
QIconDirInfo dirInfo(directoryKey);
dirInfo.size = size;
- QString type = indexReader.value(directoryKey +
- QLatin1String("/Type")
- ).toString();
+ QString type = indexReader.value(directoryKey + "/Type"_L1).toString();
- if (type == QLatin1String("Fixed"))
+ if (type == "Fixed"_L1)
dirInfo.type = QIconDirInfo::Fixed;
- else if (type == QLatin1String("Scalable"))
+ else if (type == "Scalable"_L1)
dirInfo.type = QIconDirInfo::Scalable;
else
dirInfo.type = QIconDirInfo::Threshold;
dirInfo.threshold = indexReader.value(directoryKey +
- QLatin1String("/Threshold"),
- 2).toInt();
+ "/Threshold"_L1,
+ 2).toInt();
- dirInfo.minSize = indexReader.value(directoryKey +
- QLatin1String("/MinSize"),
- size).toInt();
+ dirInfo.minSize = indexReader.value(directoryKey + "/MinSize"_L1, size).toInt();
- dirInfo.maxSize = indexReader.value(directoryKey +
- QLatin1String("/MaxSize"),
- size).toInt();
+ dirInfo.maxSize = indexReader.value(directoryKey + "/MaxSize"_L1, size).toInt();
+
+ dirInfo.scale = indexReader.value(directoryKey + "/Scale"_L1, 1).toInt();
+
+ const QString context = indexReader.value(directoryKey + "/Context"_L1).toString();
+ dirInfo.context = [context]() {
+ if (context == "Applications"_L1)
+ return QIconDirInfo::Applications;
+ else if (context == "MimeTypes"_L1)
+ return QIconDirInfo::MimeTypes;
+ else
+ return QIconDirInfo::UnknownContext;
+ }();
- dirInfo.scale = indexReader.value(directoryKey +
- QLatin1String("/Scale"),
- 1).toInt();
m_keyList.append(dirInfo);
}
}
}
// Parent themes provide fallbacks for missing icons
- m_parents = indexReader.value(
- QLatin1String("Icon Theme/Inherits")).toStringList();
+ m_parents = indexReader.value("Icon Theme/Inherits"_L1).toStringList();
m_parents.removeAll(QString());
-
- // Ensure a default platform fallback for all themes
- if (m_parents.isEmpty()) {
- const QString fallback = QIconLoader::instance()->fallbackThemeName();
- if (!fallback.isEmpty())
- m_parents.append(fallback);
- }
-
- // Ensure that all themes fall back to hicolor
- if (!m_parents.contains(QLatin1String("hicolor")))
- m_parents.append(QLatin1String("hicolor"));
}
#endif // settings
}
+QStringList QIconTheme::parents() const
+{
+ // Respect explicitly declared parents
+ QStringList result = m_parents;
+
+ // Ensure a default fallback for all themes
+ const QString fallback = QIconLoader::instance()->fallbackThemeName();
+ if (!fallback.isEmpty())
+ result.append(fallback);
+
+ // Ensure that all themes fall back to hicolor as the last theme
+ result.removeAll("hicolor"_L1);
+ result.append("hicolor"_L1);
+
+ return result;
+}
+
+QDebug operator<<(QDebug debug, const std::unique_ptr<QIconLoaderEngineEntry> &entry)
+{
+ QDebugStateSaver saver(debug);
+ debug.noquote() << entry->filename;
+ return debug;
+}
+
QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
const QString &iconName,
- QStringList &visited) const
+ QStringList &visited,
+ DashRule rule) const
{
+ qCDebug(lcIconLoader) << "Finding icon" << iconName << "in theme" << themeName
+ << "skipping" << visited;
+
QThemeIconInfo info;
Q_ASSERT(!themeName.isEmpty());
@@ -437,18 +456,21 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
QIconTheme &theme = themeList[themeName];
if (!theme.isValid()) {
theme = QIconTheme(themeName);
- if (!theme.isValid())
- theme = QIconTheme(fallbackThemeName());
+ if (!theme.isValid()) {
+ qCDebug(lcIconLoader) << "Theme" << themeName << "not found";
+ return info;
+ }
}
const QStringList contentDirs = theme.contentDirs();
QStringView iconNameFallback(iconName);
+ bool searchingGenericFallback = m_iconName.length() > iconName.length();
// Iterate through all icon's fallbacks in current theme
- while (info.entries.isEmpty()) {
- const QString svgIconName = iconNameFallback + QLatin1String(".svg");
- const QString pngIconName = iconNameFallback + QLatin1String(".png");
+ if (info.entries.empty()) {
+ const QString svgIconName = iconNameFallback + ".svg"_L1;
+ const QString pngIconName = iconNameFallback + ".png"_L1;
// Add all relevant files
for (int i = 0; i < contentDirs.size(); ++i) {
@@ -462,7 +484,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
if (cache->isValid()) {
const QList<QIconDirInfo> subDirsCopy = subDirs;
subDirs.clear();
- subDirs.reserve(result.count());
+ subDirs.reserve(result.size());
for (const char *s : result) {
QString path = QString::fromUtf8(s);
auto it = std::find_if(subDirsCopy.cbegin(), subDirsCopy.cend(),
@@ -475,94 +497,109 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
}
}
- QString contentDir = contentDirs.at(i) + QLatin1Char('/');
+ QString contentDir = contentDirs.at(i) + u'/';
for (int j = 0; j < subDirs.size() ; ++j) {
const QIconDirInfo &dirInfo = subDirs.at(j);
- const QString subDir = contentDir + dirInfo.path + QLatin1Char('/');
+ if (searchingGenericFallback &&
+ (dirInfo.context == QIconDirInfo::Applications ||
+ dirInfo.context == QIconDirInfo::MimeTypes))
+ continue;
+
+ const QString subDir = contentDir + dirInfo.path + u'/';
const QString pngPath = subDir + pngIconName;
if (QFile::exists(pngPath)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ auto iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir = dirInfo;
iconEntry->filename = pngPath;
// Notice we ensure that pixmap entries always come before
// scalable to preserve search order afterwards
- info.entries.prepend(iconEntry);
+ info.entries.insert(info.entries.begin(), std::move(iconEntry));
} else if (m_supportsSvg) {
const QString svgPath = subDir + svgIconName;
if (QFile::exists(svgPath)) {
- ScalableEntry *iconEntry = new ScalableEntry;
+ auto iconEntry = std::make_unique<ScalableEntry>();
iconEntry->dir = dirInfo;
iconEntry->filename = svgPath;
- info.entries.append(iconEntry);
+ info.entries.push_back(std::move(iconEntry));
}
}
}
}
- if (!info.entries.isEmpty()) {
+ if (!info.entries.empty()) {
info.iconName = iconNameFallback.toString();
- break;
}
-
- // If it's possible - find next fallback for the icon
- const int indexOfDash = iconNameFallback.lastIndexOf(QLatin1Char('-'));
- if (indexOfDash == -1)
- break;
-
- iconNameFallback.truncate(indexOfDash);
}
- if (info.entries.isEmpty()) {
+ if (info.entries.empty()) {
const QStringList parents = theme.parents();
+ qCDebug(lcIconLoader) << "Did not find matching icons in theme;"
+ << "trying parent themes" << parents
+ << "skipping visited" << visited;
+
// Search recursively through inherited themes
for (int i = 0 ; i < parents.size() ; ++i) {
const QString parentTheme = parents.at(i).trimmed();
if (!visited.contains(parentTheme)) // guard against recursion
- info = findIconHelper(parentTheme, iconName, visited);
+ info = findIconHelper(parentTheme, iconName, visited, QIconLoader::NoFallBack);
- if (!info.entries.isEmpty()) // success
+ if (!info.entries.empty()) // success
break;
}
}
+
+ if (rule == QIconLoader::FallBack && info.entries.empty()) {
+ // If it's possible - find next fallback for the icon
+ const int indexOfDash = iconNameFallback.lastIndexOf(u'-');
+ if (indexOfDash != -1) {
+ qCDebug(lcIconLoader) << "Did not find matching icons in all themes;"
+ << "trying dash fallback";
+ iconNameFallback.truncate(indexOfDash);
+ QStringList _visited;
+ info = findIconHelper(themeName, iconNameFallback.toString(), _visited, QIconLoader::FallBack);
+ }
+ }
+
return info;
}
QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
{
+ qCDebug(lcIconLoader) << "Looking up fallback icon" << iconName;
+
QThemeIconInfo info;
- const QString pngIconName = iconName + QLatin1String(".png");
- const QString xpmIconName = iconName + QLatin1String(".xpm");
- const QString svgIconName = iconName + QLatin1String(".svg");
+ const QString pngIconName = iconName + ".png"_L1;
+ const QString xpmIconName = iconName + ".xpm"_L1;
+ const QString svgIconName = iconName + ".svg"_L1;
const auto searchPaths = QIcon::fallbackSearchPaths();
for (const QString &iconDir: searchPaths) {
QDir currentDir(iconDir);
+ std::unique_ptr<QIconLoaderEngineEntry> iconEntry;
if (currentDir.exists(pngIconName)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(pngIconName);
- info.entries.append(iconEntry);
- break;
} else if (currentDir.exists(xpmIconName)) {
- PixmapEntry *iconEntry = new PixmapEntry;
+ iconEntry = std::make_unique<PixmapEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(xpmIconName);
- info.entries.append(iconEntry);
- break;
} else if (m_supportsSvg &&
currentDir.exists(svgIconName)) {
- ScalableEntry *iconEntry = new ScalableEntry;
+ iconEntry = std::make_unique<ScalableEntry>();
iconEntry->dir.type = QIconDirInfo::Fallback;
iconEntry->filename = currentDir.filePath(svgIconName);
- info.entries.append(iconEntry);
+ }
+ if (iconEntry) {
+ info.entries.push_back(std::move(iconEntry));
break;
}
}
- if (!info.entries.isEmpty())
+ if (!info.entries.empty())
info.iconName = iconName;
return info;
@@ -570,72 +607,162 @@ QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
QThemeIconInfo QIconLoader::loadIcon(const QString &name) const
{
- if (!themeName().isEmpty()) {
- QStringList visited;
- const QThemeIconInfo iconInfo = findIconHelper(themeName(), name, visited);
- if (!iconInfo.entries.isEmpty())
- return iconInfo;
+ qCDebug(lcIconLoader) << "Loading icon" << name;
+
+ m_iconName = name;
+ QThemeIconInfo iconInfo;
+ QStringList visitedThemes;
+ if (!themeName().isEmpty())
+ iconInfo = findIconHelper(themeName(), name, visitedThemes, QIconLoader::FallBack);
+
+ if (iconInfo.entries.empty() && !fallbackThemeName().isEmpty())
+ iconInfo = findIconHelper(fallbackThemeName(), name, visitedThemes, QIconLoader::FallBack);
+
+ if (iconInfo.entries.empty())
+ iconInfo = lookupFallbackIcon(name);
+
+ qCDebug(lcIconLoader) << "Resulting icon entries" << iconInfo.entries;
+ return iconInfo;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, QIconEngine *engine)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ if (engine) {
+ debug.noquote() << engine->key() << "(";
+ debug << static_cast<const void *>(engine);
+ if (!engine->isNull())
+ debug.quote() << ", " << engine->iconName();
+ else
+ debug << ", null";
+ debug << ")";
+ } else {
+ debug << "QIconEngine(nullptr)";
+ }
+ return debug;
+}
+#endif
- return lookupFallbackIcon(name);
+QIconEngine *QIconLoader::iconEngine(const QString &iconName) const
+{
+ qCDebug(lcIconLoader) << "Resolving icon engine for icon" << iconName;
+
+ std::unique_ptr<QIconEngine> iconEngine;
+ if (hasUserTheme())
+ iconEngine.reset(new QIconLoaderEngine(iconName));
+ if (!iconEngine || iconEngine->isNull()) {
+ qCDebug(lcIconLoader) << "Icon is not available from theme or fallback theme.";
+ if (auto *platformTheme = QGuiApplicationPrivate::platformTheme()) {
+ qCDebug(lcIconLoader) << "Trying platform engine.";
+ std::unique_ptr<QIconEngine> themeEngine(platformTheme->createIconEngine(iconName));
+ if (themeEngine && !themeEngine->isNull()) {
+ iconEngine = std::move(themeEngine);
+ qCDebug(lcIconLoader) << "Icon provided by platform engine.";
+ }
+ }
}
+ // We need to maintain the invariant that the QIcon has a valid engine
+ if (!iconEngine)
+ iconEngine.reset(new QIconLoaderEngine(iconName));
- return QThemeIconInfo();
+ qCDebug(lcIconLoader) << "Resulting engine" << iconEngine.get();
+ return iconEngine.release();
}
+/*!
+ \internal
+ \class QThemeIconEngine
+ \inmodule QtGui
-// -------- Icon Loader Engine -------- //
+ \brief A named-based icon engine for providing theme icons.
+ The engine supports invalidation of prior lookups, e.g. when
+ the platform theme changes or the user sets an explicit icon
+ theme.
-QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
- : m_iconName(iconName), m_key(0)
+ The actual icon lookup is handed over to an engine provided
+ by QIconLoader::iconEngine().
+*/
+
+QThemeIconEngine::QThemeIconEngine(const QString& iconName)
+ : QProxyIconEngine()
+ , m_iconName(iconName)
{
}
-QIconLoaderEngine::~QIconLoaderEngine()
+QThemeIconEngine::QThemeIconEngine(const QThemeIconEngine &other)
+ : QProxyIconEngine()
+ , m_iconName(other.m_iconName)
{
- qDeleteAll(m_info.entries);
}
-QIconLoaderEngine::QIconLoaderEngine(const QIconLoaderEngine &other)
- : QIconEngine(other),
- m_iconName(other.m_iconName),
- m_key(0)
+QString QThemeIconEngine::key() const
{
+ // Although we proxy the underlying engine, that's an implementation
+ // detail, so from the point of view of QIcon, and in terms of
+ // serialization, we are the one and only theme icon engine.
+ return u"QThemeIconEngine"_s;
}
-QIconEngine *QIconLoaderEngine::clone() const
+QIconEngine *QThemeIconEngine::clone() const
{
- return new QIconLoaderEngine(*this);
+ return new QThemeIconEngine(*this);
}
-bool QIconLoaderEngine::read(QDataStream &in) {
+bool QThemeIconEngine::read(QDataStream &in) {
in >> m_iconName;
return true;
}
-bool QIconLoaderEngine::write(QDataStream &out) const
+bool QThemeIconEngine::write(QDataStream &out) const
{
out << m_iconName;
return true;
}
-bool QIconLoaderEngine::hasIcon() const
+QIconEngine *QThemeIconEngine::proxiedEngine() const
{
- return !(m_info.entries.isEmpty());
+ const auto *iconLoader = QIconLoader::instance();
+ auto mostRecentThemeKey = iconLoader->themeKey();
+ if (mostRecentThemeKey != m_themeKey) {
+ qCDebug(lcIconLoader) << "Theme key" << mostRecentThemeKey << "is different"
+ << "than cached key" << m_themeKey << "for icon" << m_iconName;
+ m_proxiedEngine.reset(iconLoader->iconEngine(m_iconName));
+ m_themeKey = mostRecentThemeKey;
+ }
+ return m_proxiedEngine.get();
}
-// Lazily load the icon
-void QIconLoaderEngine::ensureLoaded()
+/*!
+ \internal
+ \class QIconLoaderEngine
+ \inmodule QtGui
+
+ \brief An icon engine based on icon entries collected by QIconLoader.
+
+ The design and implementation of QIconLoader is based on
+ the XDG icon specification.
+*/
+
+QIconLoaderEngine::QIconLoaderEngine(const QString& iconName)
+ : m_iconName(iconName)
+ , m_info(QIconLoader::instance()->loadIcon(m_iconName))
{
- if (!(QIconLoader::instance()->themeKey() == m_key)) {
- qDeleteAll(m_info.entries);
- m_info.entries.clear();
- m_info.iconName.clear();
+}
- Q_ASSERT(m_info.entries.size() == 0);
- m_info = QIconLoader::instance()->loadIcon(m_iconName);
- m_key = QIconLoader::instance()->themeKey();
- }
+QIconLoaderEngine::~QIconLoaderEngine() = default;
+
+QIconEngine *QIconLoaderEngine::clone() const
+{
+ Q_UNREACHABLE();
+ return nullptr; // Cannot be cloned
+}
+
+bool QIconLoaderEngine::hasIcon() const
+{
+ return !(m_info.entries.empty());
}
void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
@@ -711,25 +838,21 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &in
// Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = info.entries.size();
-
// Search for exact matches first
- for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = info.entries.at(i);
+ for (const auto &entry : info.entries) {
if (directoryMatchesSize(entry->dir, iconsize, scale)) {
- return entry;
+ return entry.get();
}
}
// Find the minimum distance icon
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = nullptr;
- for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = info.entries.at(i);
+ for (const auto &entry : info.entries) {
int distance = directorySizeDistance(entry->dir, iconsize, scale);
if (distance < minimalSize) {
minimalSize = distance;
- closestMatch = entry;
+ closestMatch = entry.get();
}
}
return closestMatch;
@@ -747,8 +870,6 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
Q_UNUSED(mode);
Q_UNUSED(state);
- ensureLoaded();
-
QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
@@ -757,7 +878,7 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
} else if (dir.type == QIconDirInfo::Fallback) {
return QIcon(entry->filename).actualSize(size, mode, state);
} else {
- int result = qMin<int>(dir.size, qMin(size.width(), size.height()));
+ int result = qMin<int>(dir.size * dir.scale, qMin(size.width(), size.height()));
return QSize(result, result);
}
}
@@ -779,7 +900,7 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st
if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
actualSize.scale(size, Qt::KeepAspectRatio);
- QString key = QLatin1String("$qt_theme_")
+ QString key = "$qt_theme_"_L1
% HexString<qint64>(basePixmap.cacheKey())
% HexString<int>(mode)
% HexString<qint64>(QGuiApplication::palette().cacheKey())
@@ -817,8 +938,6 @@ QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State
QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
QIcon::State state)
{
- ensureLoaded();
-
QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry)
return entry->pixmap(size, mode, state);
@@ -828,24 +947,21 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
QString QIconLoaderEngine::key() const
{
- return QLatin1String("QIconLoaderEngine");
+ return u"QIconLoaderEngine"_s;
}
QString QIconLoaderEngine::iconName()
{
- ensureLoaded();
return m_info.iconName;
}
bool QIconLoaderEngine::isNull()
{
- ensureLoaded();
- return m_info.entries.isEmpty();
+ return m_info.entries.empty();
}
QPixmap QIconLoaderEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
{
- ensureLoaded();
const int integerScale = qCeil(scale);
QIconLoaderEngineEntry *entry = entryForSize(m_info, size / integerScale, integerScale);
return entry ? entry->pixmap(size, mode, state) : QPixmap();
@@ -855,14 +971,13 @@ QList<QSize> QIconLoaderEngine::availableSizes(QIcon::Mode mode, QIcon::State st
{
Q_UNUSED(mode);
Q_UNUSED(state);
- ensureLoaded();
- const int N = m_info.entries.size();
+
+ const qsizetype N = qsizetype(m_info.entries.size());
QList<QSize> sizes;
sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
- for (int i = 0; i < N; ++i) {
- const QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ for (const auto &entry : m_info.entries) {
if (entry->dir.type == QIconDirInfo::Fallback) {
sizes.append(QIcon(entry->filename).availableSizes());
} else {
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index a17cea183e..3cfa9381d1 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QICONLOADER_P_H
#define QICONLOADER_P_H
@@ -58,11 +22,15 @@
#include <QtGui/QIconEngine>
#include <QtGui/QPixmapCache>
#include <private/qicon_p.h>
+#include <private/qiconengine_p.h>
#include <private/qfactoryloader_p.h>
#include <QtCore/QHash>
#include <QtCore/QList>
#include <QtCore/QTypeInfo>
+#include <vector>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QIconLoader;
@@ -70,6 +38,7 @@ class QIconLoader;
struct QIconDirInfo
{
enum Type { Fixed, Scalable, Threshold, Fallback };
+ enum Context { UnknownContext, Applications, MimeTypes };
QIconDirInfo(const QString &_path = QString()) :
path(_path),
size(0),
@@ -77,7 +46,8 @@ struct QIconDirInfo
minSize(0),
threshold(0),
scale(1),
- type(Threshold) {}
+ type(Threshold),
+ context(UnknownContext) {}
QString path;
short size;
short maxSize;
@@ -85,8 +55,9 @@ struct QIconDirInfo
short threshold;
short scale;
Type type;
+ Context context;
};
-Q_DECLARE_TYPEINFO(QIconDirInfo, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QIconDirInfo, Q_RELOCATABLE_TYPE);
class QIconLoaderEngineEntry
{
@@ -111,7 +82,7 @@ struct PixmapEntry : public QIconLoaderEngineEntry
QPixmap basePixmap;
};
-typedef QList<QIconLoaderEngineEntry*> QThemeIconEntries;
+using QThemeIconEntries = std::vector<std::unique_ptr<QIconLoaderEngineEntry>>;
struct QThemeIconInfo
{
@@ -119,6 +90,27 @@ struct QThemeIconInfo
QString iconName;
};
+class QThemeIconEngine : public QProxyIconEngine
+{
+public:
+ QThemeIconEngine(const QString& iconName = QString());
+ QIconEngine *clone() const override;
+ bool read(QDataStream &in) override;
+ bool write(QDataStream &out) const override;
+
+protected:
+ QIconEngine *proxiedEngine() const override;
+
+private:
+ QThemeIconEngine(const QThemeIconEngine &other);
+ QString key() const override;
+
+ QString m_iconName;
+ mutable uint m_themeKey = 0;
+
+ mutable std::unique_ptr<QIconEngine> m_proxiedEngine;
+};
+
class QIconLoaderEngine : public QIconEngine
{
public:
@@ -129,8 +121,6 @@ public:
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QIconEngine *clone() const override;
- bool read(QDataStream &in) override;
- bool write(QDataStream &out) const override;
QString iconName() override;
bool isNull() override;
@@ -140,14 +130,13 @@ public:
Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
private:
+ Q_DISABLE_COPY(QIconLoaderEngine)
+
QString key() const override;
bool hasIcon() const;
- void ensureLoaded();
- QIconLoaderEngine(const QIconLoaderEngine &other);
- QThemeIconInfo m_info;
QString m_iconName;
- uint m_key;
+ QThemeIconInfo m_info;
friend class QIconLoader;
};
@@ -159,7 +148,7 @@ class QIconTheme
public:
QIconTheme(const QString &name);
QIconTheme() : m_valid(false) {}
- QStringList parents() { return m_parents; }
+ QStringList parents() const;
QList<QIconDirInfo> keyList() { return m_keyList; }
QStringList contentDirs() { return m_contentDirs; }
bool isValid() { return m_valid; }
@@ -179,7 +168,7 @@ public:
QThemeIconInfo loadIcon(const QString &iconName) const;
uint themeKey() const { return m_themeKey; }
- QString themeName() const { return m_userTheme.isEmpty() ? m_systemTheme : m_userTheme; }
+ QString themeName() const;
void setThemeName(const QString &themeName);
QString fallbackThemeName() const;
void setFallbackThemeName(const QString &themeName);
@@ -191,14 +180,18 @@ public:
QIconDirInfo dirInfo(int dirindex);
static QIconLoader *instance();
void updateSystemTheme();
- void invalidateKey() { m_themeKey++; }
+ void invalidateKey();
void ensureInitialized();
bool hasUserTheme() const { return !m_userTheme.isEmpty(); }
+ QIconEngine *iconEngine(const QString &iconName) const;
+
private:
+ enum DashRule { FallBack, NoFallBack };
QThemeIconInfo findIconHelper(const QString &themeName,
const QString &iconName,
- QStringList &visited) const;
+ QStringList &visited,
+ DashRule rule) const;
QThemeIconInfo lookupFallbackIcon(const QString &iconName) const;
uint m_themeKey;
@@ -211,6 +204,7 @@ private:
mutable QStringList m_iconDirs;
mutable QHash <QString, QIconTheme> themeList;
mutable QStringList m_fallbackDirs;
+ mutable QString m_iconName;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index d05a72acc6..3bbf21320e 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1,51 +1,17 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
#include "qbuffer.h"
#include "qdatastream.h"
#include "qcolortransform.h"
+#include "qfloat16.h"
#include "qmap.h"
#include "qtransform.h"
#include "qimagereader.h"
#include "qimagewriter.h"
+#include "qrgbafloat.h"
#include "qstringlist.h"
#include "qvariant.h"
#include "qimagepixmapcleanuphooks_p.h"
@@ -55,6 +21,7 @@
#include <stdlib.h>
#include <limits.h>
#include <qpa/qplatformpixmap.h>
+#include <private/qcolorspace_p.h>
#include <private/qcolortransform_p.h>
#include <private/qmemrotate_p.h>
#include <private/qimagescale_p.h>
@@ -69,18 +36,24 @@
#include <private/qfont_p.h>
#if QT_CONFIG(thread)
-#include "qsemaphore.h"
-#include "qthreadpool.h"
+#include <qsemaphore.h>
+#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#endif
#include <qtgui_tracepoints_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+class QCmyk32;
-static inline bool isLocked(QImageData *data)
-{
- return data != nullptr && data->is_locked;
-}
+using namespace Qt::StringLiterals;
+
+// MSVC 19.28 does show spurious warning "C4723: potential divide by 0" for code that divides
+// by height() in release builds. Anyhow, all the code paths in this file are only executed
+// for valid QImage's, where height() cannot be 0. Therefore disable the warning.
+QT_WARNING_DISABLE_MSVC(4723)
#if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001)
#pragma message disable narrowptr
@@ -93,6 +66,17 @@ static inline bool isLocked(QImageData *data)
return QImage(); \
}
+Q_TRACE_PREFIX(qtgui,
+ "#include <qimagereader.h>"
+);
+
+Q_TRACE_METADATA(qtgui,
+"ENUM { } QImage::Format;" \
+"FLAGS { } Qt::ImageConversionFlags;"
+);
+
+Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode, int);
+Q_TRACE_PARAM_REPLACE(Qt::TransformationMode, int);
static QImage rotated90(const QImage &src);
static QImage rotated180(const QImage &src);
@@ -100,7 +84,7 @@ static QImage rotated270(const QImage &src);
static int next_qimage_serial_number()
{
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+ Q_CONSTINIT static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
return 1 + serial.fetchAndAddRelaxed(1);
}
@@ -112,7 +96,7 @@ QImageData::QImageData()
dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
- is_cached(false), is_locked(false), cleanupFunction(nullptr), cleanupInfo(nullptr),
+ is_cached(false), cleanupFunction(nullptr), cleanupInfo(nullptr),
paintEngine(nullptr)
{
}
@@ -124,9 +108,9 @@ QImageData::QImageData()
Creates a new image data.
Returns \nullptr if invalid parameters are give or anything else failed.
*/
-QImageData * QImageData::create(const QSize &size, QImage::Format format)
+QImageData * Q_TRACE_INSTRUMENT(qtgui) QImageData::create(const QSize &size, QImage::Format format)
{
- if (size.isEmpty() || format == QImage::Format_Invalid)
+ if (size.isEmpty() || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
return nullptr; // invalid parameter(s)
Q_TRACE_SCOPE(QImageData_create, size, format);
@@ -138,7 +122,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
if (!params.isValid())
return nullptr;
- QScopedPointer<QImageData> d(new QImageData);
+ auto d = std::make_unique<QImageData>();
switch (format) {
case QImage::Format_Mono:
@@ -166,7 +150,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
return nullptr;
d->ref.ref();
- return d.take();
+ return d.release();
}
QImageData::~QImageData()
@@ -288,6 +272,24 @@ bool QImageData::checkForAlphaPixels() const
bits += bytes_per_line;
}
} break;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied: {
+ uchar *bits = data;
+ for (int y = 0; y < height && !has_alpha_pixels; ++y) {
+ for (int x = 0; x < width; ++x)
+ has_alpha_pixels |= ((qfloat16 *)bits)[x * 4 + 3] < 1.0f;
+ bits += bytes_per_line;
+ }
+ } break;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied: {
+ uchar *bits = data;
+ for (int y = 0; y < height && !has_alpha_pixels; ++y) {
+ for (int x = 0; x < width; ++x)
+ has_alpha_pixels |= ((float *)bits)[x * 4 + 3] < 1.0f;
+ bits += bytes_per_line;
+ }
+ } break;
case QImage::Format_RGB32:
case QImage::Format_RGB16:
@@ -302,6 +304,9 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_Grayscale8:
case QImage::Format_Grayscale16:
case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_CMYK8888:
break;
case QImage::Format_Invalid:
case QImage::NImageFormats:
@@ -358,7 +363,7 @@ bool QImageData::checkForAlphaPixels() const
refer to the \l{How to Create Qt Plugins}{Plugin HowTo}.
\warning Painting on a QImage with the format
- QImage::Format_Indexed8 is not supported.
+ QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not supported.
\tableofcontents
@@ -426,7 +431,7 @@ bool QImageData::checkForAlphaPixels() const
The color of a pixel can be retrieved by passing its coordinates
to the pixel() function. The pixel() function returns the color
- as a QRgb value indepedent of the image's format.
+ as a QRgb value independent of the image's format.
In case of monochrome and 8-bit images, the colorCount() and
colorTable() functions provide information about the color
@@ -614,8 +619,8 @@ bool QImageData::checkForAlphaPixels() const
\endtable
- \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer, {Image Composition Example},
- {Image Viewer Example}, {Scribble Example}, {Pixelator Example}
+ \sa QImageReader, QImageWriter, QPixmap, QSvgRenderer,
+ {Image Composition Example}, {Scribble Example}
*/
/*!
@@ -708,30 +713,62 @@ bool QImageData::checkForAlphaPixels() const
The unused bits are always zero.
\value Format_ARGB4444_Premultiplied The image is stored using a
premultiplied 16-bit ARGB format (4-4-4-4).
- \value Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
- This is the same as the Format_RGBA8888 except alpha must always be 255. (added in Qt 5.2)
- \value Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.2]
+ Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
+ This is the same as the Format_RGBA8888 except alpha must always be 255.
+ \value [since 5.2]
+ Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
Unlike ARGB32 this is a byte-ordered format, which means the 32bit
encoding differs between big endian and little endian architectures,
being respectively (0xRRGGBBAA) and (0xAABBGGRR). The order of the colors
- is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA. (added in Qt 5.2)
- \value Format_RGBA8888_Premultiplied The image is stored using a
- premultiplied 32-bit byte-ordered RGBA format (8-8-8-8). (added in Qt 5.2)
- \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). (added in Qt 5.4)
- \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
- \value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
- \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
- \value Format_Grayscale16 The image is stored using an 16-bit grayscale format. (added in Qt 5.13)
- \value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
- This is the same as the Format_RGBA64 except alpha must always be 65535. (added in Qt 5.12)
- \value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
- RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
-
- \note Drawing into a QImage with QImage::Format_Indexed8 is not
+ is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
+ \value [since 5.2]
+ Format_RGBA8888_Premultiplied The image is stored using a
+ premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.4]
+ Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
+ \value [since 5.4]
+ Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
+ \value [since 5.5]
+ Format_Alpha8 The image is stored using an 8-bit alpha only format.
+ \value [since 5.5]
+ Format_Grayscale8 The image is stored using an 8-bit grayscale format.
+ \value [since 5.13]
+ Format_Grayscale16 The image is stored using an 16-bit grayscale format.
+ \value [since 5.12]
+ Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
+ This is the same as the Format_RGBA64 except alpha must always be 65535.
+ \value [since 5.12]
+ Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16).
+ \value [since 5.12]
+ Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
+ RGBA format (16-16-16-16).
+ \value [since 5.14]
+ Format_BGR888 The image is stored using a 24-bit BGR format.
+ \value [since 6.2]
+ Format_RGBX16FPx4 The image is stored using a four 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
+ This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA16FPx4 The image is stored using a four 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied four 16-bit halfword floating point
+ RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBX32FPx4 The image is stored using a four 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
+ This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA32FPx4 The image is stored using a four 32-bit floating point RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.2]
+ Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied four 32-bit floating point
+ RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.8]
+ Format_CMYK8888 The image is stored using a 32-bit byte-ordered CMYK format.
+
+ \note Drawing into a QImage with format QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not
supported.
\note Avoid most rendering directly to most of these formats using QPainter. Rendering
@@ -791,7 +828,7 @@ QImage::QImage(const QSize &size, Format format)
QImageData *QImageData::create(uchar *data, int width, int height, qsizetype bpl, QImage::Format format, bool readOnly, QImageCleanupFunction cleanupFunction, void *cleanupInfo)
{
- if (width <= 0 || height <= 0 || !data || format == QImage::Format_Invalid)
+ if (width <= 0 || height <= 0 || !data || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
return nullptr;
const int depth = qt_depthForFormat(format);
@@ -807,7 +844,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, qsizetype bp
// recalculate the total with this value
params.bytesPerLine = bpl;
- if (mul_overflow<qsizetype>(bpl, height, &params.totalSize))
+ if (qMulOverflow<qsizetype>(bpl, height, &params.totalSize))
return nullptr;
}
@@ -993,7 +1030,7 @@ QImage::QImage(const char * const xpm[])
if (!xpm)
return;
if (!qt_read_xpm_image_or_array(nullptr, xpm, *this))
- // Issue: Warning because the constructor may be ambigious
+ // Issue: Warning because the constructor may be ambiguous
qWarning("QImage::QImage(), XPM is not supported");
}
#endif // QT_NO_IMAGEFORMAT_XPM
@@ -1010,7 +1047,7 @@ QImage::QImage(const char * const xpm[])
QImage::QImage(const QImage &image)
: QPaintDevice()
{
- if (image.paintingActive() || isLocked(image.d)) {
+ if (image.paintingActive()) {
d = nullptr;
image.copy().swap(*this);
} else {
@@ -1042,7 +1079,7 @@ QImage::~QImage()
QImage &QImage::operator=(const QImage &image)
{
- if (image.paintingActive() || isLocked(image.d)) {
+ if (image.paintingActive()) {
operator=(image.copy());
} else {
if (image.d)
@@ -1104,6 +1141,28 @@ void QImage::detach()
}
+/*!
+ \internal
+
+ A variant for metadata-only detach, which will not detach readonly image data,
+ and only invalidate caches of the image data if asked to.
+
+ \sa detach(), isDetached()
+*/
+void QImage::detachMetadata(bool invalidateCache)
+{
+ if (d) {
+ if (d->is_cached && d->ref.loadRelaxed() == 1)
+ QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
+
+ if (d->ref.loadRelaxed() != 1)
+ *this = copy();
+
+ if (d && invalidateCache)
+ ++d->detach_no;
+ }
+}
+
static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
{
dst->dpmx = src->dpmx;
@@ -1113,9 +1172,10 @@ static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
static void copyMetadata(QImageData *dst, const QImageData *src)
{
- // Doesn't copy colortable and alpha_clut, or offset.
+ // Doesn't copy colortable and alpha_clut.
copyPhysicalMetadata(dst, src);
dst->text = src->text;
+ dst->offset = src->offset;
dst->colorSpace = src->colorSpace;
}
@@ -1160,7 +1220,7 @@ static void copyMetadata(QImage *dst, const QImage &src)
\sa QImage()
*/
-QImage QImage::copy(const QRect& r) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(const QRect& r) const
{
Q_TRACE_SCOPE(QImage_copy, r);
if (!d)
@@ -1180,7 +1240,6 @@ QImage QImage::copy(const QRect& r) const
} else
memcpy(image.bits(), bits(), d->nbytes);
image.d->colortable = d->colortable;
- image.d->offset = d->offset;
image.d->has_alpha_clut = d->has_alpha_clut;
copyMetadata(image.d, d);
return image;
@@ -1269,7 +1328,6 @@ QImage QImage::copy(const QRect& r) const
}
copyMetadata(image.d, d);
- image.d->offset = offset();
image.d->has_alpha_clut = d->has_alpha_clut;
return image;
}
@@ -1316,7 +1374,7 @@ int QImage::height() const
Returns the size of the image, i.e. its width() and height().
- \sa {QImage#Image Information}{Image Information}
+ \sa {QImage#Image Information}{Image Information}, deviceIndependentSize()
*/
QSize QImage::size() const
{
@@ -1385,7 +1443,7 @@ void QImage::setColorTable(const QList<QRgb> &colors)
{
if (!d)
return;
- detach();
+ detachMetadata(true);
// In case detach() ran out of memory
if (!d)
@@ -1449,7 +1507,7 @@ qreal QImage::devicePixelRatio() const
high-DPI image rather than a large image
(see \l{Drawing High Resolution Versions of Pixmaps and Images}).
- \sa devicePixelRatio()
+ \sa devicePixelRatio(), deviceIndependentSize()
*/
void QImage::setDevicePixelRatio(qreal scaleFactor)
{
@@ -1459,12 +1517,30 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
if (scaleFactor == d->devicePixelRatio)
return;
- detach();
+ detachMetadata();
if (d)
d->devicePixelRatio = scaleFactor;
}
/*!
+ Returns the size of the image in device independent pixels.
+
+ This value should be used when using the image size in user interface
+ size calculations.
+
+ The return value is equivalent to image.size() / image.devicePixelRatio().
+
+ \since 6.2
+*/
+QSizeF QImage::deviceIndependentSize() const
+{
+ if (!d)
+ return QSizeF(0, 0);
+ return QSizeF(d->width, d->height) / d->devicePixelRatio;
+}
+
+
+/*!
\since 5.10
Returns the image data size in bytes.
@@ -1526,7 +1602,7 @@ void QImage::setColor(int i, QRgb c)
qWarning("QImage::setColor: Index out of bound %d", i);
return;
}
- detach();
+ detachMetadata(true);
// In case detach() run out of memory
if (!d)
@@ -1674,11 +1750,11 @@ const uchar *QImage::constBits() const
the depth is 8, the lowest 8 bits are used and if the depth is 16
the lowest 16 bits are used.
- Note: QImage::pixel() returns the color of the pixel at the given
- coordinates while QColor::pixel() returns the pixel value of the
- underlying window system (essentially an index value), so normally
- you will want to use QImage::pixel() to use a color from an
- existing image or QColor::rgb() to use a specific color.
+ If the image depth is higher than 32bit the result is undefined.
+
+ \note There are no corresponding value getter, though QImage::pixelIndex()
+ will return the same value for indexed formats, and QImage::pixel() for
+ RGB32, ARGB32, and ARGB32PM formats.
\sa depth(), {QImage#Image Transformations}{Image Transformations}
*/
@@ -1709,18 +1785,40 @@ void QImage::fill(uint pixel)
w, d->height, d->bytes_per_line);
return;
} else if (d->depth == 16) {
+ if (d->format == Format_RGB444)
+ pixel |= 0xf000;
qt_rectfill<quint16>(reinterpret_cast<quint16*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
return;
} else if (d->depth == 24) {
+ if (d->format == Format_RGB666)
+ pixel |= 0xfc0000;
qt_rectfill<quint24>(reinterpret_cast<quint24*>(d->data), pixel,
0, 0, d->width, d->height, d->bytes_per_line);
return;
- } else if (d->depth == 64) {
+ } else if (d->format >= QImage::Format_RGBX64 && d->format <= QImage::Format_RGBA64_Premultiplied) {
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), QRgba64::fromArgb32(pixel),
0, 0, d->width, d->height, d->bytes_per_line);
return;
+ } else if (d->format >= QImage::Format_RGBX16FPx4 && d->format <= QImage::Format_RGBA16FPx4_Premultiplied) {
+ quint64 cu;
+ QRgbaFloat16 cf = QRgbaFloat16::fromArgb32(pixel);
+ ::memcpy(&cu, &cf, sizeof(quint64));
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), cu,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ return;
+ } else if (d->format >= QImage::Format_RGBX32FPx4 && d->format <= QImage::Format_RGBA32FPx4_Premultiplied) {
+ QRgbaFloat32 cf = QRgbaFloat32::fromArgb32(pixel);
+ uchar *data = d->data;
+ for (int y = 0; y < d->height; ++y) {
+ QRgbaFloat32 *line = reinterpret_cast<QRgbaFloat32 *>(data);
+ for (int x = 0; x < d->width; ++x)
+ line[x] = cf;
+ data += d->bytes_per_line;
+ }
+ return;
}
+ Q_ASSERT(d->depth == 32);
if (d->format == Format_RGB32)
pixel |= 0xff000000;
@@ -1781,6 +1879,8 @@ void QImage::fill(const QColor &color)
if (!d)
return;
+ QRgba64 opaque = color.rgba64();
+ opaque.setAlpha(65535);
switch (d->format) {
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
@@ -1799,12 +1899,10 @@ void QImage::fill(const QColor &color)
fill(ARGB2RGBA(qPremultiply(color.rgba())));
break;
case QImage::Format_BGR30:
- case QImage::Format_A2BGR30_Premultiplied:
- fill(qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64()));
+ fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
break;
case QImage::Format_RGB30:
- case QImage::Format_A2RGB30_Premultiplied:
- fill(qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64()));
+ fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
break;
case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba()));
@@ -1827,19 +1925,43 @@ void QImage::fill(const QColor &color)
else
fill((uint) 0);
break;
- case QImage::Format_RGBX64: {
- QRgba64 c = color.rgba64();
- c.setAlpha(65535);
- qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), c,
+ case QImage::Format_RGBX64:
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), opaque,
0, 0, d->width, d->height, d->bytes_per_line);
break;
-
- }
case QImage::Format_RGBA64:
- case QImage::Format_RGBA64_Premultiplied:
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
0, 0, d->width, d->height, d->bytes_per_line);
break;
+ case QImage::Format_RGBA64_Premultiplied:
+ qt_rectfill<quint64>(reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ break;
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:{
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (!hasAlphaChannel())
+ a = 1.0f;
+ if (depth() == 64) {
+ QRgbaFloat16 c16{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ c16 = c16.premultiplied();
+ qt_rectfill<QRgbaFloat16>(reinterpret_cast<QRgbaFloat16 *>(d->data), c16,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ } else {
+ QRgbaFloat32 c32{r, g, b, a};
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ c32 = c32.premultiplied();
+ qt_rectfill<QRgbaFloat32>(reinterpret_cast<QRgbaFloat32 *>(d->data), c32,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ }
+ break;
+ }
default: {
QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source);
@@ -1883,7 +2005,13 @@ void QImage::invertPixels(InvertMode mode)
QImage::Format originalFormat = d->format;
// Inverting premultiplied pixels would produce invalid image data.
if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) {
- if (depth() > 32) {
+ if (d->format == QImage::Format_RGBA16FPx4_Premultiplied) {
+ if (!d->convertInPlace(QImage::Format_RGBA16FPx4, { }))
+ *this = convertToFormat(QImage::Format_RGBA16FPx4);
+ } else if (d->format == QImage::Format_RGBA32FPx4_Premultiplied) {
+ if (!d->convertInPlace(QImage::Format_RGBA32FPx4, { }))
+ *this = convertToFormat(QImage::Format_RGBA32FPx4);
+ } else if (depth() > 32) {
if (!d->convertInPlace(QImage::Format_RGBA64, { }))
*this = convertToFormat(QImage::Format_RGBA64);
} else {
@@ -1902,8 +2030,32 @@ void QImage::invertPixels(InvertMode mode)
*sl++ ^= 0xff;
sl += pad;
}
- }
- else if (depth() == 64) {
+ } else if (format() >= QImage::Format_RGBX16FPx4 && format() <= QImage::Format_RGBA16FPx4_Premultiplied) {
+ qfloat16 *p = reinterpret_cast<qfloat16 *>(d->data);
+ qfloat16 *end = reinterpret_cast<qfloat16 *>(d->data + d->nbytes);
+ while (p < end) {
+ p[0] = qfloat16(1) - p[0];
+ p[1] = qfloat16(1) - p[1];
+ p[2] = qfloat16(1) - p[2];
+ if (mode == InvertRgba)
+ p[3] = qfloat16(1) - p[3];
+ p += 4;
+ }
+ } else if (format() >= QImage::Format_RGBX32FPx4 && format() <= QImage::Format_RGBA32FPx4_Premultiplied) {
+ uchar *data = d->data;
+ for (int y = 0; y < d->height; ++y) {
+ float *p = reinterpret_cast<float *>(data);
+ for (int x = 0; x < d->width; ++x) {
+ p[0] = 1.0f - p[0];
+ p[1] = 1.0f - p[1];
+ p[2] = 1.0f - p[2];
+ if (mode == InvertRgba)
+ p[3] = 1.0f - p[3];
+ p += 4;
+ }
+ data += d->bytes_per_line;
+ }
+ } else if (depth() == 64) {
quint16 *p = (quint16*)d->data;
quint16 *end = (quint16*)(d->data + d->nbytes);
quint16 xorbits = 0xffff;
@@ -1992,7 +2144,7 @@ void QImage::setColorCount(int colorCount)
return;
}
- detach();
+ detachMetadata(true);
// In case detach() ran out of memory
if (!d)
@@ -2053,7 +2205,7 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
if (!d || d->format == format)
return *this;
- if (format == Format_Invalid || d->format == Format_Invalid)
+ if (d->format == Format_Invalid || format <= Format_Invalid || format >= NImageFormats)
return QImage();
const QPixelLayout *destLayout = &qPixelLayouts[format];
@@ -2061,7 +2213,12 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
if (!converter && format > QImage::Format_Indexed8 && d->format > QImage::Format_Indexed8) {
if (qt_highColorPrecision(d->format, !destLayout->hasAlphaChannel)
&& qt_highColorPrecision(format, !hasAlphaChannel())) {
- converter = convert_generic_over_rgb64;
+#if QT_CONFIG(raster_fp)
+ if (qt_fpColorPrecision(d->format) && qt_fpColorPrecision(format))
+ converter = convert_generic_over_rgba32f;
+ else
+#endif
+ converter = convert_generic_over_rgb64;
} else
converter = convert_generic;
}
@@ -2070,7 +2227,6 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
QIMAGE_SANITYCHECK_MEMORY(image);
- image.d->offset = offset();
copyMetadata(image.d, d);
converter(image.d, d, flags);
@@ -2127,7 +2283,7 @@ static QImage convertWithPalette(const QImage &src, QImage::Format format,
QImage dest(src.size(), format);
dest.setColorTable(clut);
- QImageData::get(dest)->text = QImageData::get(src)->text;
+ copyMetadata(QImageData::get(dest), QImageData::get(src));
int h = src.height();
int w = src.width();
@@ -2183,7 +2339,7 @@ QImage QImage::convertToFormat(Format format, const QList<QRgb> &colorTable, Qt:
if (!d || d->format == format)
return *this;
- if (format == QImage::Format_Invalid)
+ if (format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
return QImage();
if (format <= QImage::Format_Indexed8)
return convertWithPalette(convertToFormat(QImage::Format_ARGB32, flags), format, colorTable);
@@ -2228,6 +2384,7 @@ bool QImage::reinterpretAsFormat(Format format)
// In case detach() ran out of memory
if (!d) {
d = oldD;
+ d->ref.ref();
return false;
}
}
@@ -2239,7 +2396,7 @@ bool QImage::reinterpretAsFormat(Format format)
/*!
\since 5.13
- Detach and convert the image to the given \a format in place.
+ Converts the image to the given \a format in place, detaching if necessary.
The specified image conversion \a flags control how the image data
is handled during the conversion process.
@@ -2249,7 +2406,10 @@ bool QImage::reinterpretAsFormat(Format format)
void QImage::convertTo(Format format, Qt::ImageConversionFlags flags)
{
- if (!d || format == QImage::Format_Invalid)
+ if (!d || format <= QImage::Format_Invalid || format >= QImage::NImageFormats)
+ return;
+
+ if (d->format == format)
return;
detach();
@@ -2391,6 +2551,14 @@ QRgb QImage::pixel(int x, int y) const
case Format_RGBA64: // Match ARGB32 behavior.
case Format_RGBA64_Premultiplied:
return reinterpret_cast<const QRgba64 *>(s)[x].toArgb32();
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4: // Match ARGB32 behavior.
+ case Format_RGBA16FPx4_Premultiplied:
+ return reinterpret_cast<const QRgbaFloat16 *>(s)[x].toArgb32();
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4: // Match ARGB32 behavior.
+ case Format_RGBA32FPx4_Premultiplied:
+ return reinterpret_cast<const QRgbaFloat32 *>(s)[x].toArgb32();
default:
break;
}
@@ -2467,7 +2635,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
((uint *)s)[x] = index_or_rgb;
return;
case Format_RGB16:
- ((quint16 *)s)[x] = qConvertRgb32To16(qUnpremultiply(index_or_rgb));
+ ((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
return;
case Format_RGBX8888:
((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
@@ -2488,6 +2656,27 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
case Format_A2RGB30_Premultiplied:
((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
return;
+ case Format_RGBX64:
+ ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb | 0xff000000);
+ return;
+ case Format_RGBA64:
+ case Format_RGBA64_Premultiplied:
+ ((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
+ return;
+ case Format_RGBX16FPx4:
+ ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb | 0xff000000);
+ return;
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied:
+ ((QRgbaFloat16 *)s)[x] = QRgbaFloat16::fromArgb32(index_or_rgb);
+ return;
+ case Format_RGBX32FPx4:
+ ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb | 0xff000000);
+ return;
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied:
+ ((QRgbaFloat32 *)s)[x] = QRgbaFloat32::fromArgb32(index_or_rgb);
+ return;
case Format_Invalid:
case NImageFormats:
Q_ASSERT(false);
@@ -2497,7 +2686,10 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
}
const QPixelLayout *layout = &qPixelLayouts[d->format];
- layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
+ if (!hasAlphaChannel())
+ layout->storeFromRGB32(s, &index_or_rgb, x, 1, nullptr, nullptr);
+ else
+ layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
}
/*!
@@ -2549,6 +2741,26 @@ QColor QImage::pixelColor(int x, int y) const
quint16 v = reinterpret_cast<const quint16 *>(s)[x];
return QColor(qRgba64(v, v, v, 0xffff));
}
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied: {
+ QRgbaFloat16 p = reinterpret_cast<const QRgbaFloat16 *>(s)[x];
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ p = p.unpremultiplied();
+ QColor color;
+ color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
+ return color;
+ }
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied: {
+ QRgbaFloat32 p = reinterpret_cast<const QRgbaFloat32 *>(s)[x];
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ p = p.unpremultiplied();
+ QColor color;
+ color.setRgbF(p.red(), p.green(), p.blue(), p.alpha());
+ return color;
+ }
default:
c = QRgba64::fromArgb32(pixel(x, y));
break;
@@ -2620,13 +2832,36 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
return;
case Format_RGBX64:
- ((QRgba64 *)s)[x] = color.rgba64();
- ((QRgba64 *)s)[x].setAlpha(65535);
- return;
case Format_RGBA64:
case Format_RGBA64_Premultiplied:
- ((QRgba64 *)s)[x] = color.rgba64();
+ ((QRgba64 *)s)[x] = c;
+ return;
+ case Format_RGBX16FPx4:
+ case Format_RGBA16FPx4:
+ case Format_RGBA16FPx4_Premultiplied: {
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (d->format == Format_RGBX16FPx4)
+ a = 1.0f;
+ QRgbaFloat16 c16f{qfloat16(r), qfloat16(g), qfloat16(b), qfloat16(a)};
+ if (d->format == Format_RGBA16FPx4_Premultiplied)
+ c16f = c16f.premultiplied();
+ ((QRgbaFloat16 *)s)[x] = c16f;
+ return;
+ }
+ case Format_RGBX32FPx4:
+ case Format_RGBA32FPx4:
+ case Format_RGBA32FPx4_Premultiplied: {
+ float r, g, b, a;
+ color.getRgbF(&r, &g, &b, &a);
+ if (d->format == Format_RGBX32FPx4)
+ a = 1.0f;
+ QRgbaFloat32 c32f{r, g, b, a};
+ if (d->format == Format_RGBA32FPx4_Premultiplied)
+ c32f = c32f.premultiplied();
+ ((QRgbaFloat32 *)s)[x] = c32f;
return;
+ }
default:
setPixel(x, y, c.toArgb32());
return;
@@ -2783,7 +3018,7 @@ bool QImage::isGrayscale() const
\sa isNull(), {QImage#Image Transformations}{Image
Transformations}
*/
-QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaled: Image is a null image");
@@ -2820,7 +3055,7 @@ QImage QImage::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Transf
\sa {QImage#Image Transformations}{Image Transformations}
*/
-QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaleWidth: Image is a null image");
@@ -2850,7 +3085,7 @@ QImage QImage::scaledToWidth(int w, Qt::TransformationMode mode) const
\sa {QImage#Image Transformations}{Image Transformations}
*/
-QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
{
if (!d) {
qWarning("QImage::scaleHeight: Image is a null image");
@@ -2883,7 +3118,7 @@ QImage QImage::scaledToHeight(int h, Qt::TransformationMode mode) const
\sa createHeuristicMask(), {QImage#Image Transformations}{Image
Transformations}
*/
-QImage QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::createAlphaMask(Qt::ImageConversionFlags flags) const
{
if (!d || d->format == QImage::Format_RGB32)
return QImage();
@@ -3039,6 +3274,8 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
QIMAGE_SANITYCHECK_MEMORY(maskImage);
maskImage.fill(0);
uchar *s = maskImage.bits();
+ if (!s)
+ return QImage();
if (depth() == 32) {
for (int h = 0; h < d->height; h++) {
@@ -3185,6 +3422,9 @@ inline void do_mirror(QImageData *dst, QImageData *src, bool horizontal, bool ve
}
switch (depth) {
+ case 128:
+ do_mirror_data<QRgbaFloat32>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
+ break;
case 64:
do_mirror_data<quint64>(dst, src, dstX0, dstY0, dstXIncr, dstYIncr, w, h);
break;
@@ -3330,7 +3570,7 @@ static inline void rgbSwapped_generic(int width, int height, const QImage *src,
/*!
\internal
*/
-QImage QImage::rgbSwapped_helper() const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::rgbSwapped_helper() const
{
if (isNull())
return *this;
@@ -3411,25 +3651,9 @@ QImage QImage::rgbSwapped_helper() const
}
}
break;
- case Format_RGBX64:
- case Format_RGBA64:
- case Format_RGBA64_Premultiplied:
- res = QImage(d->width, d->height, d->format);
- QIMAGE_SANITYCHECK_MEMORY(res);
- for (int i = 0; i < d->height; i++) {
- QRgba64 *q = reinterpret_cast<QRgba64 *>(res.scanLine(i));
- const QRgba64 *p = reinterpret_cast<const QRgba64 *>(constScanLine(i));
- const QRgba64 *end = p + d->width;
- while (p < end) {
- QRgba64 c = *p;
- *q = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
- p++;
- q++;
- }
- }
- break;
default:
res = QImage(d->width, d->height, d->format);
+ QIMAGE_SANITYCHECK_MEMORY(res);
rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]);
break;
}
@@ -3523,19 +3747,6 @@ void QImage::rgbSwapped_inplace()
}
}
break;
- case Format_RGBX64:
- case Format_RGBA64:
- case Format_RGBA64_Premultiplied:
- for (int i = 0; i < d->height; i++) {
- QRgba64 *p = reinterpret_cast<QRgba64 *>(scanLine(i));
- QRgba64 *end = p + d->width;
- while (p < end) {
- QRgba64 c = *p;
- *p = QRgba64::fromRgba64(c.blue(), c.green(), c.red(), c.alpha());
- p++;
- }
- }
- break;
default:
rgbSwapped_generic(d->width, d->height, this, this, &qPixelLayouts[d->format]);
break;
@@ -3581,11 +3792,10 @@ bool QImage::load(QIODevice* device, const char* format)
}
/*!
- \fn bool QImage::loadFromData(const uchar *data, int len, const char *format)
+ \since 6.2
- Loads an image from the first \a len bytes of the given binary \a
- data. Returns \c true if the image was successfully loaded; otherwise
- invalidates the image and returns \c false.
+ Loads an image from the given QByteArrayView \a data. Returns \c true if the image was
+ successfully loaded; otherwise invalidates the image and returns \c false.
The loader attempts to read the image using the specified \a format, e.g.,
PNG or JPG. If \a format is not specified (which is the default), the
@@ -3594,13 +3804,26 @@ bool QImage::load(QIODevice* device, const char* format)
\sa {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
*/
-bool QImage::loadFromData(const uchar *data, int len, const char *format)
+bool QImage::loadFromData(QByteArrayView data, const char *format)
{
- *this = fromData(data, len, format);
+ *this = fromData(data, format);
return !isNull();
}
/*!
+ \fn bool QImage::loadFromData(const uchar *data, int len, const char *format)
+
+ \overload
+
+ Loads an image from the first \a len bytes of the given binary \a data.
+*/
+
+bool QImage::loadFromData(const uchar *buf, int len, const char *format)
+{
+ return loadFromData(QByteArrayView(buf, len), format);
+}
+
+/*!
\fn bool QImage::loadFromData(const QByteArray &data, const char *format)
\overload
@@ -3609,12 +3832,11 @@ bool QImage::loadFromData(const uchar *data, int len, const char *format)
*/
/*!
- \fn QImage QImage::fromData(const uchar *data, int size, const char *format)
+ \since 6.2
- Constructs a QImage from the first \a size bytes of the given
- binary \a data. The loader attempts to read the image using the
- specified \a format. If \a format is not specified (which is the default),
- the loader probes the data for a header to guess the file format.
+ Constructs an image from the given QByteArrayView \a data. The loader attempts to read the image
+ using the specified \a format. If \a format is not specified (which is the default), the loader
+ probes the data for a header to guess the file format.
If \a format is specified, it must be one of the values returned by
QImageReader::supportedImageFormats().
@@ -3624,9 +3846,9 @@ bool QImage::loadFromData(const uchar *data, int len, const char *format)
\sa load(), save(), {QImage#Reading and Writing Image Files}{Reading and Writing Image Files}
*/
-QImage QImage::fromData(const uchar *data, int size, const char *format)
+QImage QImage::fromData(QByteArrayView data, const char *format)
{
- QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(data), size);
+ QByteArray a = QByteArray::fromRawData(data.constData(), data.size());
QBuffer b;
b.setData(a);
b.open(QIODevice::ReadOnly);
@@ -3634,11 +3856,25 @@ QImage QImage::fromData(const uchar *data, int size, const char *format)
}
/*!
+ \fn QImage QImage::fromData(const uchar *data, int size, const char *format)
+
+ \overload
+
+ Constructs a QImage from the first \a size bytes of the given binary \a data.
+*/
+
+QImage QImage::fromData(const uchar *data, int size, const char *format)
+{
+ return fromData(QByteArrayView(data, size), format);
+}
+
+/*!
\fn QImage QImage::fromData(const QByteArray &data, const char *format)
\overload
- Loads an image from the given QByteArray \a data.
+ Constructs a QImage from the given QByteArray \a data.
+
*/
/*!
@@ -3690,10 +3926,15 @@ bool QImage::save(QIODevice* device, const char* format, int quality) const
bool QImageData::doImageIO(const QImage *image, QImageWriter *writer, int quality) const
{
if (quality > 100 || quality < -1)
- qWarning("QPixmap::save: Quality out of range [-1, 100]");
+ qWarning("QImage::save: Quality out of range [-1, 100]");
if (quality >= 0)
writer->setQuality(qMin(quality,100));
- return writer->write(*image);
+ const bool result = writer->write(*image);
+#ifdef QT_DEBUG
+ if (!result)
+ qWarning("QImage::save: failed to write image - %s", qPrintable(writer->errorString()));
+#endif
+ return result;
}
/*****************************************************************************
@@ -3778,7 +4019,7 @@ bool QImage::operator==(const QImage & i) const
return false;
// obviously different stuff?
- if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format)
+ if (i.d->height != d->height || i.d->width != d->width || i.d->format != d->format || i.d->colorSpace != d->colorSpace)
return false;
if (d->format != Format_RGB32) {
@@ -3882,9 +4123,9 @@ int QImage::dotsPerMeterY() const
*/
void QImage::setDotsPerMeterX(int x)
{
- if (!d || !x)
+ if (!d || !x || d->dpmx == x)
return;
- detach();
+ detachMetadata();
if (d)
d->dpmx = x;
@@ -3904,9 +4145,9 @@ void QImage::setDotsPerMeterX(int x)
*/
void QImage::setDotsPerMeterY(int y)
{
- if (!d || !y)
+ if (!d || !y || d->dpmy == y)
return;
- detach();
+ detachMetadata();
if (d)
d->dpmy = y;
@@ -3936,9 +4177,9 @@ QPoint QImage::offset() const
*/
void QImage::setOffset(const QPoint& p)
{
- if (!d)
+ if (!d || d->offset == p)
return;
- detach();
+ detachMetadata();
if (d)
d->offset = p;
@@ -3974,7 +4215,7 @@ QString QImage::text(const QString &key) const
QString tmp;
for (auto it = d->text.begin(), end = d->text.end(); it != end; ++it)
- tmp += it.key() + QLatin1String(": ") + it.value().simplified() + QLatin1String("\n\n");
+ tmp += it.key() + ": "_L1 + it.value().simplified() + "\n\n"_L1;
if (!tmp.isEmpty())
tmp.chop(2); // remove final \n\n
return tmp;
@@ -4008,7 +4249,7 @@ void QImage::setText(const QString &key, const QString &value)
{
if (!d)
return;
- detach();
+ detachMetadata();
if (d)
d->text.insert(key, value);
@@ -4405,8 +4646,12 @@ int QImage::bitPlaneCount() const
bpc = 12;
break;
case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
bpc = 48;
break;
+ case QImage::Format_RGBX32FPx4:
+ bpc = 96;
+ break;
default:
bpc = qt_depthForFormat(d->format);
break;
@@ -4425,7 +4670,8 @@ int QImage::bitPlaneCount() const
if necessary. To avoid unnecessary conversion the result is returned in the format
internally used, and not in the original format.
*/
-QImage QImage::smoothScaled(int w, int h) const {
+QImage QImage::smoothScaled(int w, int h) const
+{
QImage src = *this;
switch (src.format()) {
case QImage::Format_RGB32:
@@ -4439,14 +4685,28 @@ QImage QImage::smoothScaled(int w, int h) const {
case QImage::Format_RGBA64_Premultiplied:
break;
case QImage::Format_RGBA64:
- src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
+ case QImage::Format_Grayscale16:
+ src.convertTo(QImage::Format_RGBA64_Premultiplied);
+ break;
+#endif
+#if QT_CONFIG(raster_fp)
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ break;
+ case QImage::Format_RGBX16FPx4:
+ src.convertTo(QImage::Format_RGBX32FPx4);
+ break;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4:
+ src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
break;
#endif
default:
if (src.hasAlphaChannel())
- src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ src.convertTo(QImage::Format_ARGB32_Premultiplied);
else
- src = src.convertToFormat(QImage::Format_RGB32);
+ src.convertTo(QImage::Format_RGB32);
}
src = qSmoothScaleImage(src, w, h);
if (!src.isNull())
@@ -4457,6 +4717,8 @@ QImage QImage::smoothScaled(int w, int h) const {
static QImage rotated90(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4485,6 +4747,8 @@ static QImage rotated180(const QImage &image)
return image.mirrored(true, true);
QImage out(image.width(), image.height(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4497,6 +4761,8 @@ static QImage rotated180(const QImage &image)
static QImage rotated270(const QImage &image)
{
QImage out(image.height(), image.width(), image.format());
+ if (out.isNull())
+ return out;
copyMetadata(&out, image);
if (image.colorCount() > 0)
out.setColorTable(image.colorTable());
@@ -4527,7 +4793,7 @@ static QImage rotated270(const QImage &image)
image where not all pixels are covered by the transformed pixels of the
original image. In such cases, those background pixels will be assigned a
transparent color value, and the transformed image will be given a format
- with an alpha channel, even if the orginal image did not have that.
+ with an alpha channel, even if the original image did not have that.
The transformation \a matrix is internally adjusted to compensate
for unwanted translation; i.e. the image produced is the smallest
@@ -4542,12 +4808,15 @@ static QImage rotated270(const QImage &image)
Transformations}
*/
-QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
+QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode ) const
{
if (!d)
return QImage();
- Q_TRACE_SCOPE(QImage_transformed, matrix, mode);
+ Q_TRACE_PARAM_REPLACE(const QTransform &, double[9]);
+ Q_TRACE_SCOPE(QImage_transformed, QList<double>({matrix.m11(), matrix.m12(), matrix.m13(),
+ matrix.m21(), matrix.m22(), matrix.m23(),
+ matrix.m31(), matrix.m32(), matrix.m33()}).data(), mode);
// source image data
const int ws = width();
@@ -4568,13 +4837,8 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
else if (mat.m11() == -1. && mat.m22() == -1.)
return rotated180(*this);
- if (mode == Qt::FastTransformation) {
- hd = qRound(qAbs(mat.m22()) * hs);
- wd = qRound(qAbs(mat.m11()) * ws);
- } else {
- hd = int(qAbs(mat.m22()) * hs + 0.9999);
- wd = int(qAbs(mat.m11()) * ws + 0.9999);
- }
+ hd = qRound(qAbs(mat.m22()) * hs);
+ wd = qRound(qAbs(mat.m11()) * ws);
scale_xform = true;
// The paint-based scaling is only bilinear, and has problems
// with scaling smoothly more than 2x down.
@@ -4624,14 +4888,24 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
|| (ws * hs) >= (1<<20)
#endif
) {
+ QImage scaledImage;
if (mat.m11() < 0.0F && mat.m22() < 0.0F) { // horizontal/vertical flip
- return smoothScaled(wd, hd).mirrored(true, true).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(true, true);
} else if (mat.m11() < 0.0F) { // horizontal flip
- return smoothScaled(wd, hd).mirrored(true, false).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(true, false);
} else if (mat.m22() < 0.0F) { // vertical flip
- return smoothScaled(wd, hd).mirrored(false, true).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd).mirrored(false, true);
} else { // no flipping
- return smoothScaled(wd, hd).convertToFormat(format());
+ scaledImage = smoothScaled(wd, hd);
+ }
+
+ switch (format()) {
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ return scaledImage;
+ default:
+ return scaledImage.convertToFormat(format());
}
}
}
@@ -4673,7 +4947,14 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
if (target_format >= QImage::Format_RGB32) {
// Prevent QPainter from applying devicePixelRatio corrections
- const QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
+ QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
+ if (sImage.d != d
+ && (d->format == QImage::Format_MonoLSB
+ || d->format == QImage::Format_Mono
+ || d->format == QImage::Format_Indexed8)) {
+ sImage.d->colortable = d->colortable;
+ sImage.d->has_alpha_clut = d->has_alpha_clut;
+ }
Q_ASSERT(sImage.devicePixelRatio() == 1);
Q_ASSERT(sImage.devicePixelRatio() == dImage.devicePixelRatio());
@@ -4743,9 +5024,12 @@ void QImage::setColorSpace(const QColorSpace &colorSpace)
return;
if (d->colorSpace == colorSpace)
return;
- if (!isDetached()) // Detach only if shared, not for read-only data.
- detach();
- d->colorSpace = colorSpace;
+ if (colorSpace.isValid() && !qt_compatibleColorModel(pixelFormat().colorModel(), colorSpace.colorModel()))
+ return;
+
+ detachMetadata(false);
+ if (d)
+ d->colorSpace = colorSpace;
}
/*!
@@ -4755,20 +5039,60 @@ void QImage::setColorSpace(const QColorSpace &colorSpace)
If the image has no valid color space, the method does nothing.
+ \note If \a colorSpace is not compatible with the current format, the image
+ will be converted to one that is.
+
\sa convertedToColorSpace(), setColorSpace()
*/
void QImage::convertToColorSpace(const QColorSpace &colorSpace)
{
- if (!d)
- return;
- if (!d->colorSpace.isValid())
+ if (!d || !d->colorSpace.isValid())
return;
- if (!colorSpace.isValid()) {
+ if (!colorSpace.isValidTarget()) {
qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
return;
}
- detach();
+ if (d->colorSpace == colorSpace)
+ return;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), colorSpace.colorModel())) {
+ *this = convertedToColorSpace(colorSpace);
+ return;
+ }
applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace));
+ if (d->ref.loadRelaxed() != 1)
+ detachMetadata(false);
+ d->colorSpace = colorSpace;
+}
+
+/*!
+ \since 6.8
+
+ Converts the image to \a colorSpace and \a format.
+
+ If the image has no valid color space, the method does nothing,
+ nor if the color space is not compatible with with the format.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \sa convertedToColorSpace(), setColorSpace()
+*/
+void QImage::convertToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags)
+{
+ if (!d || !d->colorSpace.isValid())
+ return;
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertToColorSpace: Output colorspace is not valid";
+ return;
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(format).colorModel(), colorSpace.colorModel())) {
+ qWarning() << "QImage::convertToColorSpace: Color space is not compatible with format";
+ return;
+ }
+
+ if (d->colorSpace == colorSpace)
+ return convertTo(format, flags);
+ applyColorTransform(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
d->colorSpace = colorSpace;
}
@@ -4779,14 +5103,56 @@ void QImage::convertToColorSpace(const QColorSpace &colorSpace)
If the image has no valid color space, a null QImage is returned.
- \sa convertToColorSpace()
+ \note If \a colorSpace is not compatible with the current format,
+ the returned image will also be converted to a format this is.
+ For more control over returned image format, see the three argument
+ overload of this method.
+
+ \sa convertToColorSpace(), colorTransformed()
*/
QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace) const
{
- if (!d || !d->colorSpace.isValid() || !colorSpace.isValid())
+ if (!d || !d->colorSpace.isValid())
return QImage();
- QImage image = copy();
- image.convertToColorSpace(colorSpace);
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
+ return QImage();
+ }
+ if (d->colorSpace == colorSpace)
+ return *this;
+ QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace));
+ image.setColorSpace(colorSpace);
+ return image;
+}
+
+/*!
+ \since 6.8
+
+ Returns the image converted to \a colorSpace and \a format.
+
+ If the image has no valid color space, a null QImage is returned.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \sa colorTransformed()
+*/
+QImage QImage::convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags) const
+{
+ if (!d || !d->colorSpace.isValid())
+ return QImage();
+ if (!colorSpace.isValidTarget()) {
+ qWarning() << "QImage::convertedToColorSpace: Output colorspace is not valid";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(format).colorModel(), colorSpace.colorModel())) {
+ qWarning() << "QImage::convertedToColorSpace: Color space is not compatible with format";
+ return QImage();
+ }
+ if (d->colorSpace == colorSpace)
+ return convertedTo(format, flags);
+ QImage image = colorTransformed(d->colorSpace.transformationToColorSpace(colorSpace), format, flags);
+ image.setColorSpace(colorSpace);
return image;
}
@@ -4809,31 +5175,59 @@ QColorSpace QImage::colorSpace() const
*/
void QImage::applyColorTransform(const QColorTransform &transform)
{
+ if (transform.isIdentity())
+ return;
+
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel) ||
+ !qt_compatibleColorModel(pixelFormat().colorModel(), QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel)) {
+ qWarning() << "QImage::applyColorTransform can not apply format switching transform without switching format";
+ return;
+ }
+
+ detach();
+ if (!d)
+ return;
+ if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
+ for (int i = 0; i < d->colortable.size(); ++i)
+ d->colortable[i] = transform.map(d->colortable[i]);
+ return;
+ }
QImage::Format oldFormat = format();
- if (depth() > 32) {
- if (format() != QImage::Format_RGBX64 && format() != QImage::Format_RGBA64
- && format() != QImage::Format_RGBA64_Premultiplied)
- *this = std::move(*this).convertToFormat(QImage::Format_RGBA64);
- } else if (format() != QImage::Format_ARGB32 && format() != QImage::Format_RGB32
- && format() != QImage::Format_ARGB32_Premultiplied) {
+ if (qt_fpColorPrecision(oldFormat)) {
+ if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
+ && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
+ convertTo(QImage::Format_RGBA32FPx4);
+ } else if (depth() > 32) {
+ if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
+ && oldFormat != QImage::Format_RGBA64_Premultiplied)
+ convertTo(QImage::Format_RGBA64);
+ } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
+ && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
+ && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
if (hasAlphaChannel())
- *this = std::move(*this).convertToFormat(QImage::Format_ARGB32);
+ convertTo(QImage::Format_ARGB32);
else
- *this = std::move(*this).convertToFormat(QImage::Format_RGB32);
+ convertTo(QImage::Format_RGB32);
}
QColorTransformPrivate::TransformFlags flags = QColorTransformPrivate::Unpremultiplied;
switch (format()) {
case Format_ARGB32_Premultiplied:
case Format_RGBA64_Premultiplied:
+ case Format_RGBA32FPx4_Premultiplied:
flags = QColorTransformPrivate::Premultiplied;
break;
+ case Format_Grayscale8:
+ case Format_Grayscale16:
case Format_RGB32:
+ case Format_CMYK8888:
case Format_RGBX64:
+ case Format_RGBX32FPx4:
flags = QColorTransformPrivate::InputOpaque;
break;
case Format_ARGB32:
case Format_RGBA64:
+ case Format_RGBA32FPx4:
break;
default:
Q_UNREACHABLE();
@@ -4841,26 +5235,54 @@ void QImage::applyColorTransform(const QColorTransform &transform)
std::function<void(int,int)> transformSegment;
- if (depth() > 32) {
+ if (format() == Format_Grayscale8) {
transformSegment = [&](int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
- QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(y));
- transform.d->apply(scanline, scanline, width(), flags);
+ uint8_t *scanline = reinterpret_cast<uint8_t *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->applyGray(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (format() == Format_Grayscale16) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ uint16_t *scanline = reinterpret_cast<uint16_t *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->applyGray(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (qt_fpColorPrecision(format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QRgbaFloat32 *scanline = reinterpret_cast<QRgbaFloat32 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (depth() > 32) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QRgba64 *scanline = reinterpret_cast<QRgba64 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
+ }
+ };
+ } else if (oldFormat == QImage::Format_CMYK8888) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ QCmyk32 *scanline = reinterpret_cast<QCmyk32 *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
}
};
} else {
transformSegment = [&](int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
- QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(y));
- transform.d->apply(scanline, scanline, width(), flags);
+ QRgb *scanline = reinterpret_cast<QRgb *>(d->data + y * d->bytes_per_line);
+ QColorTransformPrivate::get(transform)->apply(scanline, scanline, width(), flags);
}
};
}
#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
- int segments = sizeInBytes() / (1<<16);
+ int segments = (qsizetype(width()) * height()) >> 16;
segments = std::min(segments, height());
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -4881,6 +5303,549 @@ void QImage::applyColorTransform(const QColorTransform &transform)
*this = std::move(*this).convertToFormat(oldFormat);
}
+/*!
+ \since 6.8
+
+ Applies the color transformation \a transform to all pixels in the image, and converts the format of the image to \a toFormat.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+*/
+void QImage::applyColorTransform(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags)
+{
+ if (!d)
+ return;
+ if (transform.isIdentity())
+ return convertTo(toFormat, flags);
+
+ *this = colorTransformed(transform, toFormat, flags);
+}
+
+/*!
+ \since 6.4
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \note If \a transform has a source color space which is incompatible with the format of this image,
+ returns a null QImage. If \a transform has a target color space which is incompatible with the format
+ of this image, the image will also be converted to a compatible format. For more control about the
+ choice of the target pixel format, see the three argument overload of this method.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform) const &
+{
+ if (!d)
+ return QImage();
+ if (transform.isIdentity())
+ return *this;
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), outColorModel)) {
+ // All model switching transforms are opaque in at least one end.
+ switch (outColorModel) {
+ case QColorSpace::ColorModel::Rgb:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
+ case QColorSpace::ColorModel::Gray:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
+ case QColorSpace::ColorModel::Cmyk:
+ return colorTransformed(transform, QImage::Format_CMYK8888);
+ case QColorSpace::ColorModel::Undefined:
+ break;
+ }
+ return QImage();
+ }
+
+ QImage image = copy();
+ image.applyColorTransform(transform);
+ return image;
+}
+
+static bool isRgb32Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool isRgb64Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool isRgb32fpx4Data(QImage::Format f)
+{
+ switch (f) {
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+/*!
+ \since 6.8
+
+ Returns the image color transformed using \a transform on all pixels in the image, returning an image of format \a toFormat.
+
+ The specified image conversion \a flags control how the image data
+ is handled during the format conversion process.
+
+ \note If \a transform has a source color space which is incompatible with the format of this image,
+ or a target color space that is incompatible with \a toFormat, returns a null QImage.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format toFormat, Qt::ImageConversionFlags flags) const &
+{
+ if (!d)
+ return QImage();
+ if (toFormat == QImage::Format_Invalid)
+ toFormat = format();
+ if (transform.isIdentity())
+ return convertedTo(toFormat, flags);
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(toPixelFormat(toFormat).colorModel(), outColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid output color space for transform";
+ return QImage();
+ }
+
+ QImage fromImage = *this;
+
+ QImage::Format tmpFormat = toFormat;
+ switch (toFormat) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ // can be output natively
+ break;
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_RGBX8888:
+ tmpFormat = QImage::Format_RGB32;
+ break;
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ tmpFormat = QImage::Format_ARGB32;
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ tmpFormat = QImage::Format_RGBX64;
+ break;
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ tmpFormat = QImage::Format_RGBA64;
+ break;
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ tmpFormat = QImage::Format_RGBA32FPx4;
+ break;
+ case QImage::Format_Alpha8:
+ return convertedTo(QImage::Format_Alpha8);
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ Q_UNREACHABLE();
+ break;
+ }
+ QColorSpace::ColorModel inColorData = qt_csColorData(pixelFormat().colorModel());
+ QColorSpace::ColorModel outColorData = qt_csColorData(toPixelFormat(toFormat).colorModel());
+ // Ensure only precision increasing transforms
+ if (inColorData != outColorData) {
+ if (fromImage.format() == QImage::Format_Grayscale8 && outColorData == QColorSpace::ColorModel::Rgb)
+ tmpFormat = QImage::Format_RGB32;
+ else if (tmpFormat == QImage::Format_Grayscale8 && qt_highColorPrecision(fromImage.format()))
+ tmpFormat = QImage::Format_Grayscale16;
+ else if (fromImage.format() == QImage::Format_Grayscale16 && outColorData == QColorSpace::ColorModel::Rgb)
+ tmpFormat = QImage::Format_RGBX64;
+ } else {
+ if (tmpFormat == QImage::Format_Grayscale8 && fromImage.format() == QImage::Format_Grayscale16)
+ tmpFormat = QImage::Format_Grayscale16;
+ else if (qt_fpColorPrecision(fromImage.format()) && !qt_fpColorPrecision(tmpFormat))
+ tmpFormat = QImage::Format_RGBA32FPx4;
+ else if (isRgb32Data(tmpFormat) && qt_highColorPrecision(fromImage.format(), true))
+ tmpFormat = QImage::Format_RGBA64;
+ }
+
+ QImage toImage(size(), tmpFormat);
+ copyMetadata(&toImage, *this);
+
+ std::function<void(int, int)> transformSegment;
+ QColorTransformPrivate::TransformFlags transFlags = QColorTransformPrivate::Unpremultiplied;
+
+ if (inColorData != outColorData) {
+ // Needs color model switching transform
+ if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Rgb) {
+ // Gray -> RGB
+ if (format() == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Gray && outColorData == QColorSpace::ColorModel::Cmyk) {
+ // Gray -> CMYK
+ if (format() == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(d->data + y * d->bytes_per_line);
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(d->data + y * d->bytes_per_line);
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Gray) {
+ // RGB -> Gray
+ if (tmpFormat == QImage::Format_Grayscale8) {
+ fromImage.convertTo(QImage::Format_RGB32);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ fromImage.convertTo(QImage::Format_RGBX64);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Gray) {
+ // CMYK -> Gray
+ if (tmpFormat == QImage::Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyReturnGray(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Cmyk && outColorData == QColorSpace::ColorModel::Rgb) {
+ // CMYK -> RGB
+ if (isRgb32Data(tmpFormat) ) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else if (isRgb64Data(tmpFormat)) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ } else {
+ Q_ASSERT(isRgb32fpx4Data(tmpFormat));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), QColorTransformPrivate::InputOpaque);
+ }
+ };
+ }
+ } else if (inColorData == QColorSpace::ColorModel::Rgb && outColorData == QColorSpace::ColorModel::Cmyk) {
+ // RGB -> CMYK
+ if (!fromImage.hasAlphaChannel())
+ transFlags = QColorTransformPrivate::InputOpaque;
+ else if (qPixelLayouts[fromImage.format()].premultiplied)
+ transFlags = QColorTransformPrivate::Premultiplied;
+ if (isRgb32Data(fromImage.format()) ) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb64Data(fromImage.format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else {
+ Q_ASSERT(isRgb32fpx4Data(fromImage.format()));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ }
+ } else {
+ Q_UNREACHABLE();
+ }
+ } else {
+ // Conversion on same color model
+ if (pixelFormat().colorModel() == QPixelFormat::Indexed) {
+ for (int i = 0; i < d->colortable.size(); ++i)
+ fromImage.d->colortable[i] = transform.map(d->colortable[i]);
+ return fromImage.convertedTo(toFormat, flags);
+ }
+
+ QImage::Format oldFormat = format();
+ if (qt_fpColorPrecision(oldFormat)) {
+ if (oldFormat != QImage::Format_RGBX32FPx4 && oldFormat != QImage::Format_RGBA32FPx4
+ && oldFormat != QImage::Format_RGBA32FPx4_Premultiplied)
+ fromImage.convertTo(QImage::Format_RGBA32FPx4);
+ } else if (qt_highColorPrecision(oldFormat, true)) {
+ if (oldFormat != QImage::Format_RGBX64 && oldFormat != QImage::Format_RGBA64
+ && oldFormat != QImage::Format_RGBA64_Premultiplied && oldFormat != QImage::Format_Grayscale16)
+ fromImage.convertTo(QImage::Format_RGBA64);
+ } else if (oldFormat != QImage::Format_ARGB32 && oldFormat != QImage::Format_RGB32
+ && oldFormat != QImage::Format_ARGB32_Premultiplied && oldFormat != QImage::Format_CMYK8888
+ && oldFormat != QImage::Format_Grayscale8 && oldFormat != QImage::Format_Grayscale16) {
+ if (hasAlphaChannel())
+ fromImage.convertTo(QImage::Format_ARGB32);
+ else
+ fromImage.convertTo(QImage::Format_RGB32);
+ }
+
+ if (!fromImage.hasAlphaChannel())
+ transFlags = QColorTransformPrivate::InputOpaque;
+ else if (qPixelLayouts[fromImage.format()].premultiplied)
+ transFlags = QColorTransformPrivate::Premultiplied;
+
+ if (fromImage.format() == Format_Grayscale8) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint8 *in_scanline = reinterpret_cast<const quint8 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (tmpFormat == Format_Grayscale8) {
+ quint8 *out_scanline = reinterpret_cast<quint8 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(tmpFormat == Format_Grayscale16);
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ } else if (fromImage.format() == Format_Grayscale16) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const quint16 *in_scanline = reinterpret_cast<const quint16 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ quint16 *out_scanline = reinterpret_cast<quint16 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->applyGray(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (fromImage.format() == Format_CMYK8888) {
+ Q_ASSERT(tmpFormat == Format_CMYK8888);
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QCmyk32 *in_scanline = reinterpret_cast<const QCmyk32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QCmyk32 *out_scanline = reinterpret_cast<QCmyk32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb32fpx4Data(fromImage.format())) {
+ Q_ASSERT(isRgb32fpx4Data(tmpFormat));
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgbaFloat32 *in_scanline = reinterpret_cast<const QRgbaFloat32 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ };
+ } else if (isRgb64Data(fromImage.format())) {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgba64 *in_scanline = reinterpret_cast<const QRgba64 *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (isRgb32fpx4Data(tmpFormat)) {
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(isRgb64Data(tmpFormat));
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ } else {
+ transformSegment = [&](int yStart, int yEnd) {
+ for (int y = yStart; y < yEnd; ++y) {
+ const QRgb *in_scanline = reinterpret_cast<const QRgb *>(fromImage.constBits() + y * fromImage.bytesPerLine());
+ if (isRgb32fpx4Data(tmpFormat)) {
+ QRgbaFloat32 *out_scanline = reinterpret_cast<QRgbaFloat32 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else if (isRgb64Data(tmpFormat)) {
+ QRgba64 *out_scanline = reinterpret_cast<QRgba64 *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ } else {
+ Q_ASSERT(isRgb32Data(tmpFormat));
+ QRgb *out_scanline = reinterpret_cast<QRgb *>(toImage.d->data + y * toImage.bytesPerLine());
+ QColorTransformPrivate::get(transform)->apply(out_scanline, in_scanline, width(), transFlags);
+ }
+ }
+ };
+ }
+ }
+
+#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
+ int segments = (qsizetype(width()) * height()) >> 16;
+ segments = std::min(segments, height());
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (height() - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ transformSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+ } else
+#endif
+ transformSegment(0, height());
+
+ if (tmpFormat != toFormat)
+ toImage.convertTo(toFormat);
+
+ return toImage;
+}
+
+/*!
+ \since 6.4
+ \overload
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform) &&
+{
+ if (!d)
+ return QImage();
+
+ QColorSpace::ColorModel inColorModel = QColorTransformPrivate::get(transform)->colorSpaceIn->colorModel;
+ QColorSpace::ColorModel outColorModel = QColorTransformPrivate::get(transform)->colorSpaceOut->colorModel;
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), inColorModel)) {
+ qWarning() << "QImage::colorTransformed: Invalid input color space for transform";
+ return QImage();
+ }
+ if (!qt_compatibleColorModel(pixelFormat().colorModel(), outColorModel)) {
+ // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
+ switch (outColorModel) {
+ case QColorSpace::ColorModel::Rgb:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_RGBX64 : QImage::Format_RGB32);
+ case QColorSpace::ColorModel::Gray:
+ return colorTransformed(transform, qt_highColorPrecision(format(), true) ? QImage::Format_Grayscale16 : QImage::Format_Grayscale8);
+ case QColorSpace::ColorModel::Cmyk:
+ return colorTransformed(transform, QImage::Format_CMYK8888);
+ case QColorSpace::ColorModel::Undefined:
+ break;
+ }
+ return QImage();
+ }
+
+ applyColorTransform(transform);
+ return std::move(*this);
+}
+
+/*!
+ \since 6.8
+ \overload
+
+ Returns the image color transformed using \a transform on all pixels in the image.
+
+ \sa applyColorTransform()
+*/
+QImage QImage::colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags) &&
+{
+ // There is currently no inplace conversion of both colorspace and format, so just use the normal version.
+ return colorTransformed(transform, format, flags);
+}
bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFlags flags)
{
@@ -4899,6 +5864,10 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
// any direct ones are probably better even if not inplace.
if (qt_highColorPrecision(newFormat, !qPixelLayouts[newFormat].hasAlphaChannel)
&& qt_highColorPrecision(format, !qPixelLayouts[format].hasAlphaChannel)) {
+#if QT_CONFIG(raster_fp)
+ if (qt_fpColorPrecision(format) && qt_fpColorPrecision(newFormat))
+ return convert_generic_inplace_over_rgba32f(this, newFormat, flags);
+#endif
return convert_generic_inplace_over_rgb64(this, newFormat, flags);
}
return convert_generic_inplace(this, newFormat, flags);
@@ -5324,6 +6293,97 @@ static constexpr QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX16FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA16FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA16FPx4_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 16,
+ /*GREEN*/ 16,
+ /*BLUE*/ 16,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 16,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBX32FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA32FPx4:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_RGBA32FPx4_Premultiplied:
+ QPixelFormat(QPixelFormat::RGB,
+ /*RED*/ 32,
+ /*GREEN*/ 32,
+ /*BLUE*/ 32,
+ /*FOURTH*/ 0,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 32,
+ /*ALPHA USAGE*/ QPixelFormat::UsesAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtEnd,
+ /*PREMULTIPLIED*/ QPixelFormat::Premultiplied,
+ /*INTERPRETATION*/ QPixelFormat::FloatingPoint,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
+ //QImage::Format_CMYK8888:
+ QPixelFormat(QPixelFormat::CMYK,
+ /*RED*/ 8,
+ /*GREEN*/ 8,
+ /*BLUE*/ 8,
+ /*FOURTH*/ 8,
+ /*FIFTH*/ 0,
+ /*ALPHA*/ 0,
+ /*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
+ /*ALPHA POSITION*/ QPixelFormat::AtBeginning,
+ /*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
+ /*INTERPRETATION*/ QPixelFormat::UnsignedInteger,
+ /*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
static_assert(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);
@@ -5340,7 +6400,7 @@ QPixelFormat QImage::pixelFormat() const noexcept
*/
QPixelFormat QImage::toPixelFormat(QImage::Format format) noexcept
{
- Q_ASSERT(static_cast<int>(format) < NImageFormats);
+ Q_ASSERT(static_cast<int>(format) < NImageFormats && static_cast<int>(format) >= 0);
return pixelformats[format];
}
@@ -5384,12 +6444,11 @@ QMap<QString, QString> qt_getImageText(const QImage &image, const QString &descr
QMap<QString, QString> qt_getImageTextFromDescription(const QString &description)
{
QMap<QString, QString> text;
- const auto pairs = QStringView{description}.split(u"\n\n");
- for (const auto &pair : pairs) {
- int index = pair.indexOf(QLatin1Char(':'));
- if (index >= 0 && pair.indexOf(QLatin1Char(' ')) < index) {
+ for (const auto &pair : QStringView{description}.tokenize(u"\n\n")) {
+ int index = pair.indexOf(u':');
+ if (index >= 0 && pair.indexOf(u' ') < index) {
if (!pair.trimmed().isEmpty())
- text.insert(QLatin1String("Description"), pair.toString().simplified());
+ text.insert("Description"_L1, pair.toString().simplified());
} else {
const auto key = pair.left(index);
if (!key.trimmed().isEmpty())
@@ -5400,3 +6459,5 @@ QMap<QString, QString> qt_getImageTextFromDescription(const QString &description
}
QT_END_NAMESPACE
+
+#include "moc_qimage.cpp"
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index ae63c758f4..cba50e5e4c 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGE_H
#define QIMAGE_H
@@ -47,6 +11,7 @@
#include <QtGui/qpixelformat.h>
#include <QtGui/qtransform.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qbytearrayview.h>
#include <QtCore/qrect.h>
#include <QtCore/qstring.h>
#include <QtCore/qcontainerfwd.h>
@@ -104,6 +69,13 @@ public:
Format_RGBA64_Premultiplied,
Format_Grayscale16,
Format_BGR888,
+ Format_RGBX16FPx4,
+ Format_RGBA16FPx4,
+ Format_RGBA16FPx4_Premultiplied,
+ Format_RGBX32FPx4,
+ Format_RGBA32FPx4,
+ Format_RGBA32FPx4_Premultiplied,
+ Format_CMYK8888,
#ifndef Q_QDOC
NImageFormats
#endif
@@ -125,14 +97,14 @@ public:
QImage(const QImage &);
QImage(QImage &&other) noexcept
- : QPaintDevice(), d(qExchange(other.d, nullptr))
+ : QPaintDevice(), d(std::exchange(other.d, nullptr))
{}
~QImage();
QImage &operator=(const QImage &);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QImage)
void swap(QImage &other) noexcept
- { qSwap(d, other.d); }
+ { qt_ptr_swap(d, other.d); }
bool isNull() const;
@@ -219,6 +191,7 @@ public:
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
+ QSizeF deviceIndependentSize() const;
void fill(uint pixel);
void fill(const QColor &color);
@@ -258,24 +231,33 @@ public:
void invertPixels(InvertMode = InvertRgb);
QColorSpace colorSpace() const;
- [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &) const;
- void convertToColorSpace(const QColorSpace &);
- void setColorSpace(const QColorSpace &);
-
+ [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &colorSpace) const;
+ [[nodiscard]] QImage convertedToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) const;
+ void convertToColorSpace(const QColorSpace &colorSpace);
+ void convertToColorSpace(const QColorSpace &colorSpace, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ void setColorSpace(const QColorSpace &colorSpace);
+
+ QImage colorTransformed(const QColorTransform &transform) const &;
+ QImage colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) const &;
+ QImage colorTransformed(const QColorTransform &transform) &&;
+ QImage colorTransformed(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor) &&;
void applyColorTransform(const QColorTransform &transform);
+ void applyColorTransform(const QColorTransform &transform, QImage::Format format, Qt::ImageConversionFlags flags = Qt::AutoColor);
bool load(QIODevice *device, const char *format);
bool load(const QString &fileName, const char *format = nullptr);
- bool loadFromData(const uchar *buf, int len, const char *format = nullptr);
- bool loadFromData(const QByteArray &data, const char *aformat = nullptr)
- { return loadFromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), aformat); }
+ bool loadFromData(QByteArrayView data, const char *format = nullptr);
+ bool loadFromData(const uchar *buf, int len, const char *format = nullptr); // ### Qt 7: qsizetype
+ bool loadFromData(const QByteArray &data, const char *format = nullptr) // ### Qt 7: drop
+ { return loadFromData(QByteArrayView(data), format); }
bool save(const QString &fileName, const char *format = nullptr, int quality = -1) const;
bool save(QIODevice *device, const char *format = nullptr, int quality = -1) const;
- static QImage fromData(const uchar *data, int size, const char *format = nullptr);
- static QImage fromData(const QByteArray &data, const char *format = nullptr)
- { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); }
+ static QImage fromData(QByteArrayView data, const char *format = nullptr);
+ static QImage fromData(const uchar *data, int size, const char *format = nullptr); // ### Qt 7: qsizetype
+ static QImage fromData(const QByteArray &data, const char *format = nullptr) // ### Qt 7: drop
+ { return fromData(QByteArrayView(data), format); }
qint64 cacheKey() const;
@@ -318,8 +300,9 @@ protected:
bool convertToFormat_inplace(Format format, Qt::ImageConversionFlags flags);
QImage smoothScaled(int w, int h) const;
+ void detachMetadata(bool invalidateCache = false);
+
private:
- friend class QWSOnScreenSurface;
QImageData *d;
friend class QRasterPlatformPixmap;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 3f9eb08fdf..a806954df2 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -1,44 +1,10 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qguiapplication_p.h>
+#include <private/qcolortransform_p.h>
#include <private/qcolortrclut_p.h>
+#include <private/qcmyk_p.h>
#include <private/qdrawhelper_p.h>
#include <private/qendian_p.h>
#include <private/qpixellayout_p.h>
@@ -46,9 +12,11 @@
#include <private/qimage_p.h>
#include <qendian.h>
+#include <qrgbafloat.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
+#include <private/qthreadpool_p.h>
#ifdef Q_OS_WASM
// WebAssembly has threads; however we can't block the main thread.
#else
@@ -198,7 +166,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToARGB32PM;
if (dest->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -234,10 +202,10 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
};
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
- int segments = src->nbytes / (1<<16);
+ int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -289,10 +257,10 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
}
};
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
- int segments = src->nbytes / (1<<16);
+ int segments = (qsizetype(src->width) * src->height) >> 16;
segments = std::min(segments, src->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
return convertSegment(0, src->height);
@@ -312,6 +280,61 @@ void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::Ima
#endif
}
+#if QT_CONFIG(raster_fp)
+void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(dest->format >= QImage::Format_RGBX16FPx4);
+ Q_ASSERT(src->format >= QImage::Format_RGBX16FPx4);
+
+ const FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[src->format];
+ const ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dest->format];
+
+ auto convertSegment = [=](int yStart, int yEnd) {
+ QRgbaFloat32 buf[BufferSize];
+ QRgbaFloat32 *buffer = buf;
+ const uchar *srcData = src->data + yStart * src->bytes_per_line;
+ uchar *destData = dest->data + yStart * dest->bytes_per_line;
+ for (int y = yStart; y < yEnd; ++y) {
+ int x = 0;
+ while (x < src->width) {
+ int l = src->width - x;
+ if (dest->depth == 128)
+ buffer = reinterpret_cast<QRgbaFloat32 *>(destData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const QRgbaFloat32 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
+ store(destData, ptr, x, l, nullptr, nullptr);
+ x += l;
+ }
+ srcData += src->bytes_per_line;
+ destData += dest->bytes_per_line;
+ }
+ };
+#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+ int segments = (qsizetype(src->width) * src->height) >> 16;
+ segments = std::min(segments, src->height);
+
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ if (segments <= 1 || !threadPool || threadPool->contains(QThread::currentThread()))
+ return convertSegment(0, src->height);
+
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (src->height - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ convertSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+#else
+ convertSegment(0, src->height);
+#endif
+}
+#endif
+
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags)
{
// Cannot be used with indexed formats or between formats with different pixel depths.
@@ -336,7 +359,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
return false;
}
- Q_ASSERT(destLayout->bpp != QPixelLayout::BPP64);
+ Q_ASSERT(destLayout->bpp < QPixelLayout::BPP64);
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
@@ -361,7 +384,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
- fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToARGB32PM;
if (data->format == QImage::Format_RGB32)
store = storeRGB32FromARGB32;
else
@@ -396,9 +419,9 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
}
};
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
- int segments = data->nbytes / (1<<16);
+ int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -463,9 +486,8 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
- // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
- fetch = qPixelLayouts[data->format + 1].fetchToRGBA64PM;
- store = qStoreFromRGBA64PM[dst_format + 1];
+ fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToRGBA64PM;
+ store = qStoreFromRGBA64PM[qt_toPremultipliedFormat(dst_format)];
}
auto convertSegment = [=](int yStart, int yEnd) {
@@ -490,9 +512,103 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
}
};
#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
- int segments = data->nbytes / (1<<16);
+ int segments = (qsizetype(data->width) * data->height) >> 16;
+ segments = std::min(segments, data->height);
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
+ if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
+ QSemaphore semaphore;
+ int y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (data->height - y) / (segments - i);
+ threadPool->start([&, y, yn]() {
+ convertSegment(y, y + yn);
+ semaphore.release(1);
+ });
+ y += yn;
+ }
+ semaphore.acquire(segments);
+ if (data->bytes_per_line != params.bytesPerLine) {
+ // Compress segments to a continuous block
+ y = 0;
+ for (int i = 0; i < segments; ++i) {
+ int yn = (data->height - y) / (segments - i);
+ uchar *srcData = data->data + data->bytes_per_line * y;
+ uchar *destData = data->data + params.bytesPerLine * y;
+ if (srcData != destData)
+ memmove(destData, srcData, params.bytesPerLine * yn);
+ y += yn;
+ }
+ }
+ } else
+#endif
+ convertSegment(0, data->height);
+ if (params.totalSize != data->nbytes) {
+ Q_ASSERT(params.totalSize < data->nbytes);
+ void *newData = realloc(data->data, params.totalSize);
+ if (newData) {
+ data->data = (uchar *)newData;
+ data->nbytes = params.totalSize;
+ }
+ data->bytes_per_line = params.bytesPerLine;
+ }
+ data->depth = destDepth;
+ data->format = dst_format;
+ return true;
+}
+
+#if QT_CONFIG(raster_fp)
+bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format >= QImage::Format_RGBX16FPx4);
+ Q_ASSERT(dst_format >= QImage::Format_RGBX16FPx4);
+ const int destDepth = qt_depthForFormat(dst_format);
+ if (data->depth < destDepth)
+ return false;
+
+ const QPixelLayout *srcLayout = &qPixelLayouts[data->format];
+ const QPixelLayout *destLayout = &qPixelLayouts[dst_format];
+
+ QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes };
+ if (data->depth != destDepth) {
+ params = QImageData::calculateImageParameters(data->width, data->height, destDepth);
+ if (!params.isValid())
+ return false;
+ }
+
+ FetchAndConvertPixelsFuncFP fetch = qFetchToRGBA32F[data->format];
+ ConvertAndStorePixelsFuncFP store = qStoreFromRGBA32F[dst_format];
+ if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
+ destLayout->hasAlphaChannel && !destLayout->premultiplied) {
+ // Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
+ fetch = qFetchToRGBA32F[qt_toPremultipliedFormat(data->format)];
+ store = qStoreFromRGBA32F[qt_toPremultipliedFormat(dst_format)];
+ }
+
+ auto convertSegment = [=](int yStart, int yEnd) {
+ QRgbaFloat32 buf[BufferSize];
+ QRgbaFloat32 *buffer = buf;
+ uchar *srcData = data->data + yStart * data->bytes_per_line;
+ uchar *destData = srcData;
+ for (int y = yStart; y < yEnd; ++y) {
+ int x = 0;
+ while (x < data->width) {
+ int l = data->width - x;
+ if (srcLayout->bpp == QPixelLayout::BPP32FPx4)
+ buffer = reinterpret_cast<QRgbaFloat32 *>(srcData) + x;
+ else
+ l = qMin(l, BufferSize);
+ const QRgbaFloat32 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
+ store(destData, ptr, x, l, nullptr, nullptr);
+ x += l;
+ }
+ srcData += data->bytes_per_line;
+ destData += params.bytesPerLine;
+ }
+ };
+#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
+ int segments = (qsizetype(data->width) * data->height) >> 16;
segments = std::min(segments, data->height);
- QThreadPool *threadPool = QThreadPool::globalInstance();
+ QThreadPool *threadPool = QThreadPoolPrivate::qtGuiInstance();
if (segments > 1 && threadPool && !threadPool->contains(QThread::currentThread())) {
QSemaphore semaphore;
int y = 0;
@@ -533,6 +649,7 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
data->format = dst_format;
return true;
}
+#endif
static void convert_passthrough(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
@@ -916,8 +1033,7 @@ static inline uint qUnpremultiplyRgb30(uint rgb30)
case 3:
return rgb30;
}
- Q_UNREACHABLE();
- return 0;
+ Q_UNREACHABLE_RETURN(0);
}
template<bool rgbswap>
@@ -1206,11 +1322,11 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
- const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
+ const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToRGBA64PM;
for (int i = 0; i < src->height; ++i) {
fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
- src_data += src->bytes_per_line;;
+ src_data += src->bytes_per_line;
dest_data += dest->bytes_per_line;
}
}
@@ -1259,103 +1375,107 @@ static bool convert_RGBA64_to_RGBx64_inplace(QImageData *data, Qt::ImageConversi
return true;
}
-static void convert_RGBA64_to_RGBA64PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(src->format == QImage::Format_RGBA64);
- Q_ASSERT(dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(src->format == QImage::Format_Grayscale16);
+ Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64 ||
+ dest->format == QImage::Format_RGBA64_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
- const int src_pad = (src->bytes_per_line >> 3) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
- const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
- QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
for (int i = 0; i < src->height; ++i) {
- const QRgba64 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = src_data->premultiplied();
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
- }
-}
-
-static bool convert_RGBA64_to_RGBA64PM_inplace(QImageData *data, Qt::ImageConversionFlags)
-{
- Q_ASSERT(data->format == QImage::Format_RGBA64);
-
- const int pad = (data->bytes_per_line >> 3) - data->width;
- QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
-
- for (int i = 0; i < data->height; ++i) {
- const QRgba64 *end = rgb_data + data->width;
- while (rgb_data < end) {
- *rgb_data = rgb_data->premultiplied();
- ++rgb_data;
+ const quint16 *src_line = reinterpret_cast<const quint16 *>(src_data);
+ QRgba64 *dest_line = reinterpret_cast<QRgba64 *>(dest_data);
+ for (int j = 0; j < src->width; ++j) {
+ quint16 s = src_line[j];
+ dest_line[j] = qRgba64(s, s, s, 0xFFFF);
}
- rgb_data += pad;
+ src_data += sbpl;
+ dest_data += dbpl;
}
- data->format = QImage::Format_RGBA64_Premultiplied;
- return true;
}
-template<bool MaskAlpha>
-static void convert_RGBA64PM_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+template<bool Premultiplied>
+static void convert_ARGB_to_gray8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(src->format == QImage::Format_RGBA64_Premultiplied);
- Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64);
+ Q_ASSERT(dest->format == QImage::Format_Grayscale8);
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
- const int src_pad = (src->bytes_per_line >> 3) - src->width;
- const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
- const QRgba64 *src_data = reinterpret_cast<const QRgba64 *>(src->data);
- QRgba64 *dest_data = reinterpret_cast<QRgba64 *>(dest->data);
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
for (int i = 0; i < src->height; ++i) {
- const QRgba64 *end = src_data + src->width;
- while (src_data < end) {
- *dest_data = src_data->unpremultiplied();
- if (MaskAlpha)
- dest_data->setAlpha(65535);
- ++src_data;
- ++dest_data;
- }
- src_data += src_pad;
- dest_data += dest_pad;
+ const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
+ tfd->applyReturnGray(dest_data, src_line, src->width, flags);
+ src_data += sbpl;
+ dest_data += dbpl;
}
}
-template<bool MaskAlpha>
-static bool convert_RGBA64PM_to_RGBA64_inplace(QImageData *data, Qt::ImageConversionFlags)
+template<bool Premultiplied>
+static void convert_ARGB_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(data->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_Grayscale16);
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
- const int pad = (data->bytes_per_line >> 3) - data->width;
- QRgba64 *rgb_data = reinterpret_cast<QRgba64 *>(data->data);
+ const qsizetype sbpl = src->bytes_per_line;
+ const qsizetype dbpl = dest->bytes_per_line;
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
- for (int i = 0; i < data->height; ++i) {
- const QRgba64 *end = rgb_data + data->width;
- while (rgb_data < end) {
- *rgb_data = rgb_data->unpremultiplied();
- if (MaskAlpha)
- rgb_data->setAlpha(65535);
- ++rgb_data;
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
+ QRgba64 tmp_line[BufferSize];
+ for (int i = 0; i < src->height; ++i) {
+ const QRgb *src_line = reinterpret_cast<const QRgb *>(src_data);
+ quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
+ int j = 0;
+ while (j < src->width) {
+ const int len = std::min(src->width - j, BufferSize);
+ for (int k = 0; k < len; ++k)
+ tmp_line[k] = QRgba64::fromArgb32(src_line[j + k]);
+ tfd->applyReturnGray(dest_line + j, tmp_line, len, flags);
+ j += len;
}
- rgb_data += pad;
+ src_data += sbpl;
+ dest_data += dbpl;
}
- data->format = MaskAlpha ? QImage::Format_RGBX64 : QImage::Format_RGBA64;
- return true;
}
-static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+template<bool Premultiplied>
+static void convert_RGBA64_to_gray8(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
- Q_ASSERT(src->format == QImage::Format_Grayscale16);
- Q_ASSERT(dest->format == QImage::Format_RGBA64 || dest->format == QImage::Format_RGBX64 ||
- dest->format == QImage::Format_RGBA64_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_Grayscale8);
+ Q_ASSERT(src->format == QImage::Format_RGBX64 ||
+ src->format == QImage::Format_RGBA64 ||
+ src->format == QImage::Format_RGBA64_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
@@ -1364,22 +1484,36 @@ static void convert_gray16_to_RGBA64(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
+ quint16 gray_line[BufferSize];
for (int i = 0; i < src->height; ++i) {
- const quint16 *src_line = reinterpret_cast<const quint16 *>(src_data);
- QRgba64 *dest_line = reinterpret_cast<QRgba64 *>(dest_data);
- for (int j = 0; j < src->width; ++j) {
- quint16 s = src_line[j];
- dest_line[j] = qRgba64(s, s, s, 0xFFFF);
+ const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
+ uchar *dest_line = dest_data;
+ int j = 0;
+ while (j < src->width) {
+ const int len = std::min(src->width - j, BufferSize);
+ tfd->applyReturnGray(gray_line, src_line + j, len, flags);
+ for (int k = 0; k < len; ++k)
+ dest_line[j + k] = qt_div_257(gray_line[k]);
+ j += len;
}
src_data += sbpl;
dest_data += dbpl;
}
}
+template<bool Premultiplied>
static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(dest->format == QImage::Format_Grayscale16);
Q_ASSERT(src->format == QImage::Format_RGBX64 ||
+ src->format == QImage::Format_RGBA64 ||
src->format == QImage::Format_RGBA64_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
@@ -1389,18 +1523,71 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
+ const QColorTransformPrivate *tfd = QColorTransformPrivate::get(tf);
+ QColorTransformPrivate::TransformFlags flags = Premultiplied
+ ? QColorTransformPrivate::InputPremultiplied
+ : QColorTransformPrivate::Unpremultiplied;
+
for (int i = 0; i < src->height; ++i) {
const QRgba64 *src_line = reinterpret_cast<const QRgba64 *>(src_data);
quint16 *dest_line = reinterpret_cast<quint16 *>(dest_data);
- for (int j = 0; j < src->width; ++j) {
- QRgba64 s = src_line[j].unpremultiplied();
- dest_line[j] = qGray(s.red(), s.green(), s.blue());
- }
+ tfd->applyReturnGray(dest_line, src_line, src->width, flags);
src_data += sbpl;
dest_data += dbpl;
}
}
+template<bool MaskAlpha>
+static void convert_RGBA16FPM_to_RGBA16F(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGBA16FPx4_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_RGBA16FPx4 || dest->format == QImage::Format_RGBX16FPx4);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const int src_pad = (src->bytes_per_line >> 3) - src->width;
+ const int dest_pad = (dest->bytes_per_line >> 3) - dest->width;
+ const QRgbaFloat16 *src_data = reinterpret_cast<const QRgbaFloat16 *>(src->data);
+ QRgbaFloat16 *dest_data = reinterpret_cast<QRgbaFloat16 *>(dest->data);
+
+ for (int i = 0; i < src->height; ++i) {
+ const QRgbaFloat16 *end = src_data + src->width;
+ while (src_data < end) {
+ *dest_data = src_data->unpremultiplied();
+ if (MaskAlpha)
+ dest_data->setAlpha(1.0f);
+ ++src_data;
+ ++dest_data;
+ }
+ src_data += src_pad;
+ dest_data += dest_pad;
+ }
+}
+
+template<bool MaskAlpha>
+static bool convert_RGBA16FPM_to_RGBA16F_inplace(QImageData *data, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(data->format == QImage::Format_RGBA16FPx4_Premultiplied);
+
+ const int pad = (data->bytes_per_line >> 3) - data->width;
+ QRgbaFloat16 *rgb_data = reinterpret_cast<QRgbaFloat16 *>(data->data);
+
+ for (int i = 0; i < data->height; ++i) {
+ const QRgbaFloat16 *end = rgb_data + data->width;
+ while (rgb_data < end) {
+ *rgb_data = rgb_data->unpremultiplied();
+ if (MaskAlpha)
+ rgb_data->setAlpha(1.0f);
+ ++rgb_data;
+ }
+ rgb_data += pad;
+ }
+ data->format = MaskAlpha ? QImage::Format_RGBX16FPx4 : QImage::Format_RGBA16FPx4;
+ return true;
+}
+
static QList<QRgb> fix_color_table(const QList<QRgb> &ctbl, QImage::Format format)
{
QList<QRgb> colorTable = ctbl;
@@ -2164,23 +2351,29 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s
uchar translate[256];
const QList<QRgb> &colors = src->colortable;
bool simpleCase = (colors.size() == 256);
+ for (int i = 0; i < colors.size() && simpleCase; ++i) {
+ if (colors[i] != qRgb(i, i, i))
+ simpleCase = false;
+ }
+ if (simpleCase) {
+ copy_8bit_pixels(dest, src);
+ return;
+ }
+
+ QColorSpace fromCS = src->colorSpace.isValid() ? src->colorSpace : QColorSpace::SRgb;
+ QColorTransform tf = QColorSpacePrivate::get(fromCS)->transformationToXYZ();
for (int i = 0; i < colors.size(); ++i) {
- uchar gray = qGray(colors[i]);
- translate[i] = gray;
- simpleCase = simpleCase && (gray == i);
+ QRgba64 c16 = tf.map(QRgba64::fromArgb32(colors[i]));
+ translate[i] = c16.green8(); // Y from XYZ ends up in the G channel
}
- if (simpleCase)
- copy_8bit_pixels(dest, src);
- else {
- const uchar *sdata = src->data;
- uchar *ddata = dest->data;
- for (int y = 0; y < src->height; ++y) {
- for (int x = 0; x < src->width; ++x)
- ddata[x] = translate[sdata[x]];
- sdata += src->bytes_per_line;
- ddata += dest->bytes_per_line;
- }
+ const uchar *sdata = src->data;
+ uchar *ddata = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ for (int x = 0; x < src->width; ++x)
+ ddata[x] = translate[sdata[x]];
+ sdata += src->bytes_per_line;
+ ddata += dest->bytes_per_line;
}
}
@@ -2212,7 +2405,7 @@ static bool convert_Indexed8_to_Grayscale8_inplace(QImageData *data, Qt::ImageCo
if (colors.size() != 256)
return false;
for (int i = 0; i < colors.size(); ++i) {
- if (i != qGray(colors[i]))
+ if (colors[i] != qRgb(i, i, i))
return false;
}
@@ -2262,6 +2455,34 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
return true;
}
+template <bool SourceIsPremultiplied>
+static void convert_ARGB32_to_CMYK8888(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
+{
+ Q_ASSERT(src->format == QImage::Format_RGB32 ||
+ src->format == QImage::Format_ARGB32 ||
+ src->format == QImage::Format_ARGB32_Premultiplied);
+ Q_ASSERT(dest->format == QImage::Format_CMYK8888);
+ Q_ASSERT(src->width == dest->width);
+ Q_ASSERT(src->height == dest->height);
+
+ const uchar *src_data = src->data;
+ uchar *dest_data = dest->data;
+ for (int y = 0; y < src->height; ++y) {
+ const QRgb *srcRgba = reinterpret_cast<const QRgb *>(src_data);
+ uint *destCmyk = reinterpret_cast<uint *>(dest_data);
+
+ for (int x = 0; x < src->width; ++x) {
+ QRgb sourcePixel = srcRgba[x];
+ if constexpr (SourceIsPremultiplied)
+ sourcePixel = qUnpremultiply(sourcePixel);
+
+ destCmyk[x] = QCmyk32::fromRgba(sourcePixel).toUint();
+ }
+
+ src_data += src->bytes_per_line;;
+ dest_data += dest->bytes_per_line;
+ }
+}
// first index source, second dest
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] = {};
@@ -2298,6 +2519,8 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGB32][QImage::Format_Indexed8] = convert_RGB_to_Indexed8;
qimage_converter_map[QImage::Format_RGB32][QImage::Format_ARGB32] = mask_alpha_converter;
qimage_converter_map[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = mask_alpha_converter;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Mono] = convert_X_to_Mono;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_MonoLSB] = convert_X_to_Mono;
@@ -2309,11 +2532,15 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_A2BGR30_Premultiplied] = convert_ARGB_to_A2RGB30<PixelOrderBGR, false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_A2RGB30_Premultiplied] = convert_ARGB_to_A2RGB30<PixelOrderRGB, false>;
qimage_converter_map[QImage::Format_ARGB32][QImage::Format_RGBA64] = convert_ARGB32_to_RGBA64<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<false>;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Mono] = convert_ARGB_PM_to_Mono;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_MonoLSB] = convert_ARGB_PM_to_Mono;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Indexed8] = convert_ARGB_PM_to_Indexed8;
qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_RGBA;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Grayscale8] = convert_ARGB_to_gray8<true>;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_Grayscale16] = convert_ARGB_to_gray16<true>;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB<false>;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB<false>;
@@ -2363,16 +2590,17 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGBX64][QImage::Format_RGBA64] = convert_passthrough;
qimage_converter_map[QImage::Format_RGBX64][QImage::Format_RGBA64_Premultiplied] = convert_passthrough;
- qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16;
+ qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGBX64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<false>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_ARGB32] = convert_RGBA64_to_ARGB32<false>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBA8888] = convert_RGBA64_to_ARGB32<true>;
qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBX64] = convert_RGBA64_to_RGBx64;
- qimage_converter_map[QImage::Format_RGBA64][QImage::Format_RGBA64_Premultiplied] = convert_RGBA64_to_RGBA64PM;
+ qimage_converter_map[QImage::Format_RGBA64][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<false>;
+ qimage_converter_map[QImage::Format_RGBA64][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<false>;
- qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBX64] = convert_RGBA64PM_to_RGBA64<true>;
- qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBA64] = convert_RGBA64PM_to_RGBA64<false>;
- qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16;
+ qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale8] = convert_RGBA64_to_gray8<true>;
+ qimage_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_Grayscale16] = convert_RGBA64_to_gray16<true>;
qimage_converter_map[QImage::Format_Grayscale16][QImage::Format_RGBX64] = convert_gray16_to_RGBA64;
qimage_converter_map[QImage::Format_Grayscale16][QImage::Format_RGBA64] = convert_gray16_to_RGBA64;
@@ -2385,6 +2613,17 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB<false>;
#endif
+ qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] = convert_passthrough;
+
+ qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] = convert_passthrough;
+
+ qimage_converter_map[QImage::Format_CMYK8888][QImage::Format_CMYK8888] = convert_passthrough;
+ qimage_converter_map[QImage::Format_RGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<false>;
+ qimage_converter_map[QImage::Format_ARGB32_Premultiplied][QImage::Format_CMYK8888] = convert_ARGB32_to_CMYK8888<true>;
+
// Inline converters:
qimage_inplace_converter_map[QImage::Format_Indexed8][QImage::Format_Grayscale8] =
convert_Indexed8_to_Grayscale8_inplace;
@@ -2486,17 +2725,20 @@ static void qInitImageConversions()
qimage_inplace_converter_map[QImage::Format_RGBA64][QImage::Format_RGBX64] =
convert_RGBA64_to_RGBx64_inplace;
- qimage_inplace_converter_map[QImage::Format_RGBA64][QImage::Format_RGBA64_Premultiplied] =
- convert_RGBA64_to_RGBA64PM_inplace;
-
- qimage_inplace_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBX64] =
- convert_RGBA64PM_to_RGBA64_inplace<true>;
- qimage_inplace_converter_map[QImage::Format_RGBA64_Premultiplied][QImage::Format_RGBA64] =
- convert_RGBA64PM_to_RGBA64_inplace<false>;
qimage_inplace_converter_map[QImage::Format_BGR888][QImage::Format_RGB888] =
convert_rgbswap_generic_inplace;
+ qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4] =
+ convert_passthrough_inplace<QImage::Format_RGBA16FPx4>;
+ qimage_inplace_converter_map[QImage::Format_RGBX16FPx4][QImage::Format_RGBA16FPx4_Premultiplied] =
+ convert_passthrough_inplace<QImage::Format_RGBA16FPx4_Premultiplied>;
+
+ qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4] =
+ convert_passthrough_inplace<QImage::Format_RGBA32FPx4>;
+ qimage_inplace_converter_map[QImage::Format_RGBX32FPx4][QImage::Format_RGBA32FPx4_Premultiplied] =
+ convert_passthrough_inplace<QImage::Format_RGBA32FPx4_Premultiplied>;
+
// Now architecture specific conversions:
#if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSSE3)
if (qCpuHasFeature(SSSE3)) {
diff --git a/src/gui/image/qimage_darwin.mm b/src/gui/image/qimage_darwin.mm
index e2ec52d2df..3744da2e32 100644
--- a/src/gui/image/qimage_darwin.mm
+++ b/src/gui/image/qimage_darwin.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
@@ -88,7 +52,7 @@ QT_BEGIN_NAMESPACE
Other formats are not supported; this function returns a null
CGImageRef for those cases. Users of this function may then
- convert the QImage to a supported formate first, for example
+ convert the QImage to a supported format first, for example
Format_ARGB32_Premultiplied.
The CGImageRef color space is set to the sRGB color space.
diff --git a/src/gui/image/qimage_mips_dspr2.cpp b/src/gui/image/qimage_mips_dspr2.cpp
index 13cca12cfa..5022e21ee8 100644
--- a/src/gui/image/qimage_mips_dspr2.cpp
+++ b/src/gui/image/qimage_mips_dspr2.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimage.h"
#include <private/qimage_p.h>
diff --git a/src/gui/image/qimage_mips_dspr2_asm.S b/src/gui/image/qimage_mips_dspr2_asm.S
index 15beab29dc..61bccdb3d1 100644
--- a/src/gui/image/qimage_mips_dspr2_asm.S
+++ b/src/gui/image/qimage_mips_dspr2_asm.S
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Imagination Technologies Limited, www.imgtec.com
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "../painting/qt_mips_asm_dsp_p.h"
diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp
index 9dbcb11db5..b513dc2894 100644
--- a/src/gui/image/qimage_neon.cpp
+++ b/src/gui/image/qimage_neon.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qimage.h>
#include <private/qimage_p.h>
@@ -54,7 +18,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons
// align dst on 128 bits
const int offsetToAlignOn16Bytes = (reinterpret_cast<quintptr>(dst) >> 2) & 0x3;
- for (int i = 0; i < offsetToAlignOn16Bytes; ++i) {
+ for (int i = 0; i < qMin(len, offsetToAlignOn16Bytes); ++i) {
*dst++ = qRgb(src[0], src[1], src[2]);
src += 3;
}
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 2fbb646c2e..0d42f94253 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGE_P_H
#define QIMAGE_P_H
@@ -57,6 +21,8 @@
#include <QtCore/private/qnumeric_p.h>
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
+#include <QtCore/qttypetraits.h>
+
QT_BEGIN_NAMESPACE
@@ -93,7 +59,6 @@ struct Q_GUI_EXPORT QImageData { // internal image data
uint ro_data : 1;
uint has_alpha_clut : 1;
uint is_cached : 1;
- uint is_locked : 1;
QImageCleanupFunction cleanupFunction;
void* cleanupInfo;
@@ -129,18 +94,18 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp
// calculate the size, taking care of overflows
qsizetype bytes_per_line;
- if (mul_overflow(width, depth, &bytes_per_line))
+ if (qMulOverflow(width, depth, &bytes_per_line))
return invalid;
- if (add_overflow(bytes_per_line, qsizetype(31), &bytes_per_line))
+ if (qAddOverflow(bytes_per_line, qsizetype(31), &bytes_per_line))
return invalid;
// bytes per scanline (must be multiple of 4)
bytes_per_line = (bytes_per_line >> 5) << 2; // can't overflow
qsizetype total_size;
- if (mul_overflow(height, bytes_per_line, &total_size))
+ if (qMulOverflow(height, bytes_per_line, &total_size))
return invalid;
qsizetype dummy;
- if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
+ if (qMulOverflow(height, qsizetype(sizeof(uchar *)), &dummy))
return invalid; // why is this here?
#if 1 || QT_VERSION < QT_VERSION_CHECK(6,0,0) // ### can only fix this if QImage dimensions are not int anymore
// Disallow images where width * depth calculations might overflow
@@ -161,6 +126,10 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
void convert_generic_over_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
+#if QT_CONFIG(raster_fp)
+void convert_generic_over_rgba32f(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags);
+bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags);
+#endif
void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha);
@@ -216,8 +185,19 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_RGBX64:
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
depth = 64;
break;
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ depth = 128;
+ break;
+ case QImage::Format_CMYK8888:
+ depth = 32;
+ break;
}
return depth;
}
@@ -247,16 +227,49 @@ inline QImage::Format qt_opaqueVersion(QImage::Format format)
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
return QImage::Format_RGBX64;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ return QImage::Format_RGBX16FPx4;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return QImage::Format_RGBX32FPx4;
case QImage::Format_ARGB32_Premultiplied:
case QImage::Format_ARGB32:
- default:
return QImage::Format_RGB32;
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ return format;
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_Alpha8:
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
}
+ return QImage::Format_RGB32;
}
inline QImage::Format qt_alphaVersion(QImage::Format format)
{
switch (format) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ return QImage::Format_ARGB32_Premultiplied;
case QImage::Format_RGB16:
return QImage::Format_ARGB8565_Premultiplied;
case QImage::Format_RGB555:
@@ -266,19 +279,120 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
case QImage::Format_RGB444:
return QImage::Format_ARGB4444_Premultiplied;
case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
return QImage::Format_RGBA8888_Premultiplied;
case QImage::Format_BGR30:
return QImage::Format_A2BGR30_Premultiplied;
case QImage::Format_RGB30:
return QImage::Format_A2RGB30_Premultiplied;
case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_Grayscale16:
return QImage::Format_RGBA64_Premultiplied;
- default:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ return QImage::Format_RGBA16FPx4_Premultiplied;
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ return QImage::Format_RGBA32FPx4_Premultiplied;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return format;
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_Alpha8:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Invalid:
+ case QImage::Format_CMYK8888:
+ case QImage::NImageFormats:
break;
}
return QImage::Format_ARGB32_Premultiplied;
}
+// Returns an opaque version that is compatible with format
+inline QImage::Format qt_maybeDataCompatibleOpaqueVersion(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_ARGB6666_Premultiplied:
+ return QImage::Format_RGB666;
+ case QImage::Format_ARGB4444_Premultiplied:
+ return QImage::Format_RGB444;
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ return QImage::Format_RGBX8888;
+ case QImage::Format_A2BGR30_Premultiplied:
+ return QImage::Format_BGR30;
+ case QImage::Format_A2RGB30_Premultiplied:
+ return QImage::Format_RGB30;
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ return QImage::Format_RGBX64;
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ return QImage::Format_RGBX16FPx4;
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return QImage::Format_RGBX32FPx4;
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ return QImage::Format_RGB32;
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_RGBX8888:
+ case QImage::Format_BGR30:
+ case QImage::Format_RGB30:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ return format; // Already opaque
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_Alpha8:
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
+ }
+ return format; // No compatible opaque versions
+}
+
+constexpr QImage::Format qt_toUnpremultipliedFormat(QImage::Format format)
+{
+ // Assumes input is already a premultiplied format with an unpremultiplied counterpart
+ // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
+ return static_cast<QImage::Format>(qToUnderlying(format) - 1);
+}
+
+constexpr QImage::Format qt_toPremultipliedFormat(QImage::Format format)
+{
+ // Assumes input is already an unpremultiplied format
+ // This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
+ return static_cast<QImage::Format>(qToUnderlying(format) + 1);
+}
+
inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
{
// Formats with higher color precision than ARGB32_Premultiplied.
@@ -294,6 +408,12 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
case QImage::Format_Grayscale16:
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
return true;
default:
break;
@@ -301,16 +421,123 @@ inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
return false;
}
+inline bool qt_fpColorPrecision(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGBX16FPx4:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBX32FPx4:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+inline QColorSpace::ColorModel qt_csColorData(QPixelFormat::ColorModel format)
+{
+ switch (format) {
+ case QPixelFormat::ColorModel::RGB:
+ case QPixelFormat::ColorModel::BGR:
+ case QPixelFormat::ColorModel::Indexed:
+ return QColorSpace::ColorModel::Rgb;
+ case QPixelFormat::ColorModel::Alpha:
+ return QColorSpace::ColorModel::Undefined; // No valid colors
+ case QPixelFormat::ColorModel::Grayscale:
+ return QColorSpace::ColorModel::Gray;
+ case QPixelFormat::ColorModel::CMYK:
+ return QColorSpace::ColorModel::Cmyk;
+ default:
+ break;
+ }
+ return QColorSpace::ColorModel::Undefined;
+}
+
+inline bool qt_compatibleColorModel(QPixelFormat::ColorModel data, QColorSpace::ColorModel cs)
+{
+ QColorSpace::ColorModel dataCs = qt_csColorData(data);
+
+ if (data == QPixelFormat::ColorModel::Alpha)
+ return true; // Alpha data has no colors and can be handled by any color space
+
+ if (cs == QColorSpace::ColorModel::Undefined || dataCs == QColorSpace::ColorModel::Undefined)
+ return false;
+
+ if (dataCs == cs)
+ return true; // Matching color models
+
+ if (dataCs == QColorSpace::ColorModel::Gray)
+ return true; // Can apply any CS with white point to Gray data
+
+ return false;
+}
-inline QImage::Format qt_maybeAlphaVersionWithSameDepth(QImage::Format format)
+inline QImage::Format qt_maybeDataCompatibleAlphaVersion(QImage::Format format)
{
- const QImage::Format toFormat = qt_alphaVersion(format);
- return qt_depthForFormat(format) == qt_depthForFormat(toFormat) ? toFormat : format;
+ switch (format) {
+ case QImage::Format_RGB32:
+ return QImage::Format_ARGB32_Premultiplied;
+ case QImage::Format_RGB666:
+ return QImage::Format_ARGB6666_Premultiplied;
+ case QImage::Format_RGB444:
+ return QImage::Format_ARGB4444_Premultiplied;
+ case QImage::Format_RGBX8888:
+ return QImage::Format_RGBA8888_Premultiplied;
+ case QImage::Format_BGR30:
+ return QImage::Format_A2BGR30_Premultiplied;
+ case QImage::Format_RGB30:
+ return QImage::Format_A2RGB30_Premultiplied;
+ case QImage::Format_RGBX64:
+ return QImage::Format_RGBA64_Premultiplied;
+ case QImage::Format_RGBX16FPx4:
+ return QImage::Format_RGBA16FPx4_Premultiplied;
+ case QImage::Format_RGBX32FPx4:
+ return QImage::Format_RGBA32FPx4_Premultiplied;
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_A2BGR30_Premultiplied:
+ case QImage::Format_A2RGB30_Premultiplied:
+ case QImage::Format_Alpha8:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ case QImage::Format_RGBA16FPx4:
+ case QImage::Format_RGBA16FPx4_Premultiplied:
+ case QImage::Format_RGBA32FPx4:
+ case QImage::Format_RGBA32FPx4_Premultiplied:
+ return format; // Already alpha versions
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB888:
+ case QImage::Format_BGR888:
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ case QImage::Format_CMYK8888:
+ case QImage::Format_Invalid:
+ case QImage::NImageFormats:
+ break;
+ }
+ return format; // No data-compatible alpha version
}
inline QImage::Format qt_opaqueVersionForPainting(QImage::Format format)
{
- return qt_opaqueVersion(format);
+ QImage::Format toFormat = qt_opaqueVersion(format);
+ // If we are switching depth anyway upgrade to RGB32
+ if (qt_depthForFormat(format) != qt_depthForFormat(toFormat) && qt_depthForFormat(toFormat) <= 32)
+ toFormat = QImage::Format_RGB32;
+ return toFormat;
}
inline QImage::Format qt_alphaVersionForPainting(QImage::Format format)
@@ -318,7 +545,7 @@ inline QImage::Format qt_alphaVersionForPainting(QImage::Format format)
QImage::Format toFormat = qt_alphaVersion(format);
#if defined(__ARM_NEON__) || defined(__SSE2__)
// If we are switching depth anyway and we have optimized ARGB32PM routines, upgrade to that.
- if (qt_depthForFormat(format) != qt_depthForFormat(toFormat))
+ if (qt_depthForFormat(format) != qt_depthForFormat(toFormat) && qt_depthForFormat(toFormat) <= 32)
toFormat = QImage::Format_ARGB32_Premultiplied;
#endif
return toFormat;
diff --git a/src/gui/image/qimage_ssse3.cpp b/src/gui/image/qimage_ssse3.cpp
index fb81a1a6c3..40f52b6ce6 100644
--- a/src/gui/image/qimage_ssse3.cpp
+++ b/src/gui/image/qimage_ssse3.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qimage.h>
#include <private/qimage_p.h>
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index 75a2f2ac65..1dcfd9a074 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QImageIOHandler
@@ -160,20 +124,15 @@
variants should return a list of supported variant names
(QList<QByteArray>) in this option.
- \value OptimizedWrite. A handler which supports this option
+ \value OptimizedWrite A handler which supports this option
is expected to turn on optimization flags when writing.
- \value ProgressiveScanWrite. A handler which supports
+ \value ProgressiveScanWrite A handler which supports
this option is expected to write the image as a progressive scan image.
- \value ImageTransformation. A handler which supports this option can read
+ \value ImageTransformation A handler which supports this option can read
the transformation metadata of an image. A handler that supports this option
should not apply the transformation itself.
-
-\if !defined(qt6)
- \value TransformedByDefault. A handler that reports support for this feature
- will have image transformation metadata applied by default on read.
-\endif
*/
/*! \enum QImageIOHandler::Transformation
@@ -580,7 +539,7 @@ bool QImageIOHandler::allocateImage(QSize size, QImage::Format format, QImage *i
image->detach();
} else {
if (const int mbLimit = QImageReader::allocationLimit()) {
- qsizetype depth = qt_depthForFormat(format);
+ qsizetype depth = qMax(qt_depthForFormat(format), 32); // Effective gui depth = 32
QImageData::ImageSizeParameters szp =
QImageData::calculateImageParameters(size.width(), size.height(), depth);
if (!szp.isValid())
@@ -652,3 +611,5 @@ QImageIOPlugin::~QImageIOPlugin()
#endif // QT_NO_IMAGEFORMATPLUGIN
QT_END_NAMESPACE
+
+#include "moc_qimageiohandler.cpp"
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 1923443997..ccd215203a 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEIOHANDLER_H
#define QIMAGEIOHANDLER_H
@@ -94,9 +58,6 @@ public:
OptimizedWrite,
ProgressiveScanWrite,
ImageTransformation
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- , TransformedByDefault
-#endif
};
enum Transformation {
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index f383e7a60e..f6d891eed9 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qimagepixmapcleanuphooks_p.h"
#include <qpa/qplatformpixmap.h>
diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 29144c6656..3a3d5aa5f8 100644
--- a/src/gui/image/qimagepixmapcleanuphooks_p.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H
#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 611cbb1df1..9366e9cbb1 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
//#define QIMAGEREADER_DEBUG
@@ -47,7 +11,6 @@
\inmodule QtGui
\reentrant
\ingroup painting
- \ingroup io
The most common way to read images is through QImage and QPixmap's
constructors, or by calling QImage::load() and
@@ -172,6 +135,10 @@
QT_BEGIN_NAMESPACE
using namespace QImageReaderWriterHelpers;
+using namespace Qt::StringLiterals;
+
+Q_TRACE_POINT(qtgui, QImageReader_read_before_reading, QImageReader *reader, const QString &filename);
+Q_TRACE_POINT(qtgui, QImageReader_read_after_reading, QImageReader *reader, bool result);
static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
const QByteArray &format,
@@ -186,7 +153,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
QByteArray suffix;
#ifndef QT_NO_IMAGEFORMATPLUGIN
- static QBasicMutex mutex;
+ Q_CONSTINIT static QBasicMutex mutex;
const auto locker = qt_scoped_lock(mutex);
typedef QMultiMap<int, QString> PluginKeyMap;
@@ -271,7 +238,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device,
}
}
} else {
- const int testIndex = keyMap.key(QLatin1String(testFormat), -1);
+ const int testIndex = keyMap.key(QLatin1StringView(testFormat), -1);
if (testIndex != -1) {
QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(testIndex));
if (plugin && plugin->capabilities(device, testFormat) & QImageIOPlugin::CanRead) {
@@ -496,7 +463,7 @@ public:
static int maxAlloc;
};
-int QImageReaderPrivate::maxAlloc = 128; // 128 MB is enough for an 8K 32bpp image
+int QImageReaderPrivate::maxAlloc = 256; // 256 MB is enough for an 8K 64bpp image
/*!
\internal
@@ -519,9 +486,9 @@ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq)
*/
QImageReaderPrivate::~QImageReaderPrivate()
{
+ delete handler;
if (deleteDevice)
delete device;
- delete handler;
}
/*!
@@ -529,6 +496,9 @@ QImageReaderPrivate::~QImageReaderPrivate()
*/
bool QImageReaderPrivate::initHandler()
{
+ if (handler)
+ return true;
+
// check some preconditions
if (!device || (!deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly))) {
imageReaderError = QImageReader::DeviceError;
@@ -559,14 +529,15 @@ bool QImageReaderPrivate::initHandler()
int currentExtension = 0;
QString fileName = file->fileName();
+ bool fileIsOpen;
do {
- file->setFileName(fileName + QLatin1Char('.')
- + QLatin1String(extensions.at(currentExtension++).constData()));
- file->open(QIODevice::ReadOnly);
- } while (!file->isOpen() && currentExtension < extensions.size());
+ file->setFileName(fileName + u'.'
+ + QLatin1StringView(extensions.at(currentExtension++).constData()));
+ fileIsOpen = file->open(QIODevice::ReadOnly);
+ } while (!fileIsOpen && currentExtension < extensions.size());
- if (!device->isOpen()) {
+ if (!fileIsOpen) {
imageReaderError = QImageReader::FileNotFoundError;
errorString = QImageReader::tr("File not found");
file->setFileName(fileName); // restore the old file name
@@ -575,7 +546,7 @@ bool QImageReaderPrivate::initHandler()
}
// assign a handler
- if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
+ if ((handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == nullptr) {
imageReaderError = QImageReader::UnsupportedFormatError;
errorString = QImageReader::tr("Unsupported image format");
return false;
@@ -588,7 +559,7 @@ bool QImageReaderPrivate::initHandler()
*/
void QImageReaderPrivate::getText()
{
- if (text.isEmpty() && (handler || initHandler()) && handler->supportsOption(QImageIOHandler::Description))
+ if (text.isEmpty() && q->supportsOption(QImageIOHandler::Description))
text = qt_getImageTextFromDescription(handler->option(QImageIOHandler::Description).toString());
}
@@ -769,7 +740,7 @@ bool QImageReader::decideFormatFromContent() const
otherwise left unchanged.
If the device is not already open, QImageReader will attempt to
- open the device in \l QIODevice::ReadOnly mode by calling
+ open the device in \l {QIODeviceBase::}{ReadOnly} mode by calling
open(). Note that this does not work for certain devices, such as
QProcess, QTcpSocket and QUdpSocket, where more logic is required
to open the device.
@@ -778,12 +749,12 @@ bool QImageReader::decideFormatFromContent() const
*/
void QImageReader::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
d->text.clear();
}
@@ -799,7 +770,7 @@ QIODevice *QImageReader::device() const
/*!
Sets the file name of QImageReader to \a fileName. Internally,
QImageReader will create a QFile object and open it in \l
- QIODevice::ReadOnly mode, and use this when reading images.
+ {QIODeviceBase::}{ReadOnly} mode, and use this when reading images.
If \a fileName does not include a file extension (e.g., .png or .bmp),
QImageReader will cycle through all supported extensions until it finds
@@ -878,10 +849,7 @@ int QImageReader::quality() const
*/
QSize QImageReader::size() const
{
- if (!d->initHandler())
- return QSize();
-
- if (d->handler->supportsOption(QImageIOHandler::Size))
+ if (supportsOption(QImageIOHandler::Size))
return d->handler->option(QImageIOHandler::Size).toSize();
return QSize();
@@ -901,10 +869,7 @@ QSize QImageReader::size() const
*/
QImage::Format QImageReader::imageFormat() const
{
- if (!d->initHandler())
- return QImage::Format_Invalid;
-
- if (d->handler->supportsOption(QImageIOHandler::ImageFormat))
+ if (supportsOption(QImageIOHandler::ImageFormat))
return (QImage::Format)d->handler->option(QImageIOHandler::ImageFormat).toInt();
return QImage::Format_Invalid;
@@ -976,6 +941,10 @@ QRect QImageReader::clipRect() const
support scaling), QImageReader will use QImage::scale() with
Qt::SmoothScaling.
+ If only one dimension is set in \a size, the other one will be
+ computed from the image's \l {size()} {natural size} so as to
+ maintain the aspect ratio.
+
\sa scaledSize(), setClipRect(), setScaledClipRect()
*/
void QImageReader::setScaledSize(const QSize &size)
@@ -1026,9 +995,7 @@ QRect QImageReader::scaledClipRect() const
*/
void QImageReader::setBackgroundColor(const QColor &color)
{
- if (!d->initHandler())
- return;
- if (d->handler->supportsOption(QImageIOHandler::BackgroundColor))
+ if (supportsOption(QImageIOHandler::BackgroundColor))
d->handler->setOption(QImageIOHandler::BackgroundColor, color);
}
@@ -1043,9 +1010,7 @@ void QImageReader::setBackgroundColor(const QColor &color)
*/
QColor QImageReader::backgroundColor() const
{
- if (!d->initHandler())
- return QColor();
- if (d->handler->supportsOption(QImageIOHandler::BackgroundColor))
+ if (supportsOption(QImageIOHandler::BackgroundColor))
return qvariant_cast<QColor>(d->handler->option(QImageIOHandler::BackgroundColor));
return QColor();
}
@@ -1060,9 +1025,7 @@ QColor QImageReader::backgroundColor() const
*/
bool QImageReader::supportsAnimation() const
{
- if (!d->initHandler())
- return false;
- if (d->handler->supportsOption(QImageIOHandler::Animation))
+ if (supportsOption(QImageIOHandler::Animation))
return d->handler->option(QImageIOHandler::Animation).toBool();
return false;
}
@@ -1074,10 +1037,7 @@ bool QImageReader::supportsAnimation() const
*/
QByteArray QImageReader::subType() const
{
- if (!d->initHandler())
- return QByteArray();
-
- if (d->handler->supportsOption(QImageIOHandler::SubType))
+ if (supportsOption(QImageIOHandler::SubType))
return d->handler->option(QImageIOHandler::SubType).toByteArray();
return QByteArray();
}
@@ -1089,10 +1049,7 @@ QByteArray QImageReader::subType() const
*/
QList<QByteArray> QImageReader::supportedSubTypes() const
{
- if (!d->initHandler())
- return QList<QByteArray>();
-
- if (d->handler->supportsOption(QImageIOHandler::SupportedSubTypes))
+ if (supportsOption(QImageIOHandler::SupportedSubTypes))
return qvariant_cast<QList<QByteArray> >(d->handler->option(QImageIOHandler::SupportedSubTypes));
return QList<QByteArray>();
}
@@ -1108,7 +1065,7 @@ QList<QByteArray> QImageReader::supportedSubTypes() const
QImageIOHandler::Transformations QImageReader::transformation() const
{
int option = QImageIOHandler::TransformationNone;
- if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::ImageTransformation))
+ if (supportsOption(QImageIOHandler::ImageTransformation))
option = d->handler->option(QImageIOHandler::ImageTransformation).toInt();
return QImageIOHandler::Transformations(option);
}
@@ -1142,10 +1099,6 @@ bool QImageReader::autoTransform() const
case QImageReaderPrivate::DoNotApplyTransform:
return false;
case QImageReaderPrivate::UsePluginDefault:
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- if (d->initHandler())
- return d->handler->supportsOption(QImageIOHandler::TransformedByDefault);
-#endif
Q_FALLTHROUGH();
default:
break;
@@ -1227,31 +1180,48 @@ bool QImageReader::read(QImage *image)
return false;
}
- if (!d->handler && !d->initHandler())
+ if (!d->initHandler())
return false;
+ QSize scaledSize = d->scaledSize;
+ if ((scaledSize.width() <= 0 && scaledSize.height() > 0) ||
+ (scaledSize.height() <= 0 && scaledSize.width() > 0)) {
+ // if only one dimension is given, let's try to calculate the second one
+ // based on the original image size and maintaining the aspect ratio
+ if (const QSize originalSize = size(); !originalSize.isEmpty()) {
+ if (scaledSize.width() <= 0) {
+ const auto ratio = qreal(scaledSize.height()) / originalSize.height();
+ scaledSize.setWidth(qRound(originalSize.width() * ratio));
+ } else {
+ const auto ratio = qreal(scaledSize.width()) / originalSize.width();
+ scaledSize.setHeight(qRound(originalSize.height() * ratio));
+ }
+ }
+ }
+
+ const bool supportScaledSize = supportsOption(QImageIOHandler::ScaledSize) && scaledSize.isValid();
+ const bool supportClipRect = supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull();
+ const bool supportScaledClipRect = supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull();
+
// set the handler specific options.
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid()) {
- if ((d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull())
- || d->clipRect.isNull()) {
+ if (supportScaledSize) {
+ if (supportClipRect || d->clipRect.isNull()) {
// Only enable the ScaledSize option if there is no clip rect, or
// if the handler also supports ClipRect.
- d->handler->setOption(QImageIOHandler::ScaledSize, d->scaledSize);
+ d->handler->setOption(QImageIOHandler::ScaledSize, scaledSize);
}
}
- if (d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull())
+ if (supportClipRect)
d->handler->setOption(QImageIOHandler::ClipRect, d->clipRect);
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull())
+ if (supportScaledClipRect)
d->handler->setOption(QImageIOHandler::ScaledClipRect, d->scaledClipRect);
- if (d->handler->supportsOption(QImageIOHandler::Quality))
+ if (supportsOption(QImageIOHandler::Quality))
d->handler->setOption(QImageIOHandler::Quality, d->quality);
// read the image
+ QString filename = fileName();
if (Q_TRACE_ENABLED(QImageReader_read_before_reading)) {
- QString fileName = QStringLiteral("unknown");
- if (QFile *file = qobject_cast<QFile *>(d->device))
- fileName = file->fileName();
- Q_TRACE(QImageReader_read_before_reading, this, fileName);
+ Q_TRACE(QImageReader_read_before_reading, this, filename.isEmpty() ? u"unknown"_s : filename);
}
const bool result = d->handler->read(image);
@@ -1266,9 +1236,9 @@ bool QImageReader::read(QImage *image)
// provide default implementations for any unsupported image
// options
- if (d->handler->supportsOption(QImageIOHandler::ClipRect) && !d->clipRect.isNull()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportClipRect) {
+ if (supportScaledSize) {
+ if (supportScaledClipRect) {
// all features are supported by the handler; nothing to do.
} else {
// the image is already scaled, so apply scaled clipping.
@@ -1276,12 +1246,12 @@ bool QImageReader::read(QImage *image)
*image = image->copy(d->scaledClipRect);
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledClipRect) {
// supports scaled clipping but not scaling, most
// likely a broken handler.
} else {
- if (d->scaledSize.isValid()) {
- *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ if (scaledSize.isValid()) {
+ *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}
if (d->scaledClipRect.isValid()) {
*image = image->copy(d->scaledClipRect);
@@ -1289,8 +1259,8 @@ bool QImageReader::read(QImage *image)
}
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledSize) && d->scaledSize.isValid() && d->clipRect.isNull()) {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledSize && d->clipRect.isNull()) {
+ if (supportScaledClipRect) {
// nothing to do (ClipRect is ignored!)
} else {
// provide all workarounds.
@@ -1299,7 +1269,7 @@ bool QImageReader::read(QImage *image)
}
}
} else {
- if (d->handler->supportsOption(QImageIOHandler::ScaledClipRect) && !d->scaledClipRect.isNull()) {
+ if (supportScaledClipRect) {
// this makes no sense; a handler that supports
// ScaledClipRect but not ScaledSize is broken, and we
// can't work around it.
@@ -1307,8 +1277,8 @@ bool QImageReader::read(QImage *image)
// provide all workarounds.
if (d->clipRect.isValid())
*image = image->copy(d->clipRect);
- if (d->scaledSize.isValid())
- *image = image->scaled(d->scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ if (scaledSize.isValid())
+ *image = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (d->scaledClipRect.isValid())
*image = image->copy(d->scaledClipRect);
}
@@ -1318,8 +1288,8 @@ bool QImageReader::read(QImage *image)
// successful read; check for "@Nx" file name suffix and set device pixel ratio.
static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING");
if (!disableNxImageLoading) {
- const QByteArray suffix = QFileInfo(fileName()).baseName().right(3).toLatin1();
- if (suffix.length() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
+ const QByteArray suffix = QFileInfo(filename).baseName().right(3).toLatin1();
+ if (suffix.size() == 3 && suffix[0] == '@' && suffix[1] >= '2' && suffix[1] <= '9' && suffix[2] == 'x')
image->setDevicePixelRatio(suffix[1] - '0');
}
if (autoTransform())
@@ -1588,7 +1558,13 @@ QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeTy
*/
int QImageReader::allocationLimit()
{
- return QImageReaderPrivate::maxAlloc;
+ static int envLimit = []() {
+ bool ok = false;
+ int res = qEnvironmentVariableIntValue("QT_IMAGEIO_MAXALLOC", &ok);
+ return ok ? res : -1;
+ }();
+
+ return envLimit >= 0 ? envLimit : QImageReaderPrivate::maxAlloc;
}
/*!
@@ -1596,11 +1572,18 @@ int QImageReader::allocationLimit()
Sets the allocation limit to \a mbLimit megabytes. Images that would
require a QImage memory allocation above this limit will be rejected.
+ If \a mbLimit is 0, the allocation size check will be disabled.
This limit helps applications avoid unexpectedly large memory usage from
loading corrupt image files. It is normally not needed to change it. The
default limit is large enough for all commonly used image sizes.
+ At runtime, this value may be overridden by the environment variable \c QT_IMAGEIO_MAXALLOC.
+
+ \note The memory requirements are calculated for a minimum of 32 bits per pixel, since Qt will
+ typically convert an image to that depth when it is used in GUI. This means that the effective
+ allocation limit is significantly smaller than \a mbLimit when reading 1 bpp and 8 bpp images.
+
\sa allocationLimit()
*/
void QImageReader::setAllocationLimit(int mbLimit)
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 23c8a916d2..c5ea883c83 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEREADER_H
#define QIMAGEREADER_H
diff --git a/src/gui/image/qimagereaderwriterhelpers.cpp b/src/gui/image/qimagereaderwriterhelpers.cpp
index dd56d887a7..502b0f95f0 100644
--- a/src/gui/image/qimagereaderwriterhelpers.cpp
+++ b/src/gui/image/qimagereaderwriterhelpers.cpp
@@ -1,57 +1,23 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qimagereaderwriterhelpers_p.h"
-#include <qjsonarray.h>
+#include <qcborarray.h>
#include <qmutex.h>
#include <private/qfactoryloader_p.h>
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
namespace QImageReaderWriterHelpers {
#ifndef QT_NO_IMAGEFORMATPLUGIN
-Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
- (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats")))
-Q_GLOBAL_STATIC(QMutex, loaderMutex)
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, irhLoader,
+ (QImageIOHandlerFactoryInterface_iid, "/imageformats"_L1))
+Q_GLOBAL_STATIC(QMutex, irhLoaderMutex)
static void appendImagePluginFormats(QFactoryLoader *loader,
QImageIOPlugin::Capability cap,
@@ -81,13 +47,12 @@ static void appendImagePluginMimeTypes(QFactoryLoader *loader,
QList<QByteArray> *result,
QList<QByteArray> *resultKeys = nullptr)
{
- QList<QJsonObject> metaDataList = loader->metaData();
-
+ QList<QPluginParsedMetaData> metaDataList = loader->metaData();
const int pluginCount = metaDataList.size();
for (int i = 0; i < pluginCount; ++i) {
- const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject();
- const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray();
- const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray();
+ const QCborMap metaData = metaDataList.at(i).value(QtPluginMetaDataKeys::MetaData).toMap();
+ const QCborArray keys = metaData.value("Keys"_L1).toArray();
+ const QCborArray mimeTypes = metaData.value("MimeTypes"_L1).toArray();
QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i));
const int keyCount = keys.size();
for (int k = 0; k < keyCount; ++k) {
@@ -103,9 +68,9 @@ static void appendImagePluginMimeTypes(QFactoryLoader *loader,
QSharedPointer<QFactoryLoader> pluginLoader()
{
- loaderMutex()->lock();
- return QSharedPointer<QFactoryLoader>(loader(), [](QFactoryLoader *) {
- loaderMutex()->unlock();
+ irhLoaderMutex()->lock();
+ return QSharedPointer<QFactoryLoader>(irhLoader(), [](QFactoryLoader *) {
+ irhLoaderMutex()->unlock();
});
}
@@ -124,7 +89,7 @@ QList<QByteArray> supportedImageFormats(Capability cap)
formats << _qt_BuiltInFormats[i].extension;
#ifndef QT_NO_IMAGEFORMATPLUGIN
- appendImagePluginFormats(loader(), pluginCapability(cap), &formats);
+ appendImagePluginFormats(irhLoader(), pluginCapability(cap), &formats);
#endif // QT_NO_IMAGEFORMATPLUGIN
std::sort(formats.begin(), formats.end());
@@ -132,15 +97,17 @@ QList<QByteArray> supportedImageFormats(Capability cap)
return formats;
}
+static constexpr QByteArrayView imagePrefix() noexcept { return "image/"; }
+
QList<QByteArray> supportedMimeTypes(Capability cap)
{
QList<QByteArray> mimeTypes;
mimeTypes.reserve(_qt_NumFormats);
for (const auto &fmt : _qt_BuiltInFormats)
- mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType);
+ mimeTypes.emplace_back(imagePrefix() + fmt.mimeType);
#ifndef QT_NO_IMAGEFORMATPLUGIN
- appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes);
+ appendImagePluginMimeTypes(irhLoader(), pluginCapability(cap), &mimeTypes);
#endif // QT_NO_IMAGEFORMATPLUGIN
std::sort(mimeTypes.begin(), mimeTypes.end());
@@ -148,11 +115,11 @@ QList<QByteArray> supportedMimeTypes(Capability cap)
return mimeTypes;
}
-QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap)
+QList<QByteArray> imageFormatsForMimeType(QByteArrayView mimeType, Capability cap)
{
QList<QByteArray> formats;
- if (mimeType.startsWith("image/")) {
- const QByteArray type = mimeType.mid(sizeof("image/") - 1);
+ if (mimeType.startsWith(imagePrefix())) {
+ const QByteArrayView type = mimeType.mid(imagePrefix().size());
for (const auto &fmt : _qt_BuiltInFormats) {
if (fmt.mimeType == type && !formats.contains(fmt.extension))
formats << fmt.extension;
@@ -162,7 +129,7 @@ QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability
#ifndef QT_NO_IMAGEFORMATPLUGIN
QList<QByteArray> mimeTypes;
QList<QByteArray> keys;
- appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes, &keys);
+ appendImagePluginMimeTypes(irhLoader(), pluginCapability(cap), &mimeTypes, &keys);
for (int i = 0; i < mimeTypes.size(); ++i) {
if (mimeTypes.at(i) == mimeType) {
const auto &key = keys.at(i);
diff --git a/src/gui/image/qimagereaderwriterhelpers_p.h b/src/gui/image/qimagereaderwriterhelpers_p.h
index ae1141b3ab..930a57b536 100644
--- a/src/gui/image/qimagereaderwriterhelpers_p.h
+++ b/src/gui/image/qimagereaderwriterhelpers_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEREADERWRITERHELPERS_P_H
#define QIMAGEREADERWRITERHELPERS_P_H
@@ -130,7 +94,7 @@ enum Capability {
};
QList<QByteArray> supportedImageFormats(Capability cap);
QList<QByteArray> supportedMimeTypes(Capability cap);
-QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap);
+QList<QByteArray> imageFormatsForMimeType(QByteArrayView mimeType, Capability cap);
}
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 519a222db1..d2176e4189 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QImageWriter
@@ -45,7 +9,6 @@
\inmodule QtGui
\reentrant
\ingroup painting
- \ingroup io
QImageWriter supports setting format specific options, such as
compression level and quality, prior to storing the
@@ -133,6 +96,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
const QByteArray &format)
{
@@ -153,7 +118,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
// if there's no format, see if \a device is a file, and if so, find
// the file suffix and find support for that format among our plugins.
// this allows plugins to override our built-in handlers.
- if (QFile *file = qobject_cast<QFile *>(device)) {
+ if (QFileDevice *file = qobject_cast<QFileDevice *>(device)) {
if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
#ifndef QT_NO_IMAGEFORMATPLUGIN
const int index = keyMap.key(QString::fromLatin1(suffix), -1);
@@ -349,9 +314,9 @@ QImageWriter::QImageWriter(const QString &fileName, const QByteArray &format)
*/
QImageWriter::~QImageWriter()
{
+ delete d->handler;
if (d->deleteDevice)
delete d->device;
- delete d->handler;
delete d;
}
@@ -396,13 +361,13 @@ QByteArray QImageWriter::format() const
*/
void QImageWriter::setDevice(QIODevice *device)
{
+ delete d->handler;
+ d->handler = nullptr;
if (d->device && d->deleteDevice)
delete d->device;
d->device = device;
d->deleteDevice = false;
- delete d->handler;
- d->handler = nullptr;
}
/*!
@@ -428,17 +393,17 @@ void QImageWriter::setFileName(const QString &fileName)
}
/*!
- If the currently assigned device is a QFile, or if setFileName()
+ If the currently assigned device is a file, or if setFileName()
has been called, this function returns the name of the file
QImageWriter writes to. Otherwise (i.e., if no device has been
- assigned or the device is not a QFile), an empty QString is
+ assigned or the device is not a file), an empty QString is
returned.
\sa setFileName(), setDevice()
*/
QString QImageWriter::fileName() const
{
- QFile *file = qobject_cast<QFile *>(d->device);
+ QFileDevice *file = qobject_cast<QFileDevice *>(d->device);
return file ? file->fileName() : QString();
}
@@ -646,8 +611,8 @@ QImageIOHandler::Transformations QImageWriter::transformation() const
void QImageWriter::setText(const QString &key, const QString &text)
{
if (!d->description.isEmpty())
- d->description += QLatin1String("\n\n");
- d->description += key.simplified() + QLatin1String(": ") + text.simplified();
+ d->description += "\n\n"_L1;
+ d->description += key.simplified() + ": "_L1 + text.simplified();
}
/*!
@@ -719,7 +684,7 @@ bool QImageWriter::write(const QImage &image)
if (!d->handler->write(img))
return false;
- if (QFile *file = qobject_cast<QFile *>(d->device))
+ if (QFileDevice *file = qobject_cast<QFileDevice *>(d->device))
file->flush();
return true;
}
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 3969acbe80..b01161025a 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QIMAGEWRITER_H
#define QIMAGEWRITER_H
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 096b4f6877..435f1dced9 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*!
\class QMovie
@@ -89,7 +53,7 @@
Call supportedFormats() for a list of formats that QMovie supports.
- \sa QLabel, QImageReader, {Movie Example}
+ \sa QLabel, QImageReader
*/
/*! \enum QMovie::MovieState
@@ -180,17 +144,20 @@
#include "qrect.h"
#include "qelapsedtimer.h"
#include "qtimer.h"
-#include "qpair.h"
#include "qmap.h"
#include "qlist.h"
#include "qbuffer.h"
#include "qdir.h"
+#include "qloggingcategory.h"
#include "private/qobject_p.h"
+#include "private/qproperty_p.h"
#define QMOVIE_INVALID_DELAY -1
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
+
class QFrameInfo
{
public:
@@ -220,7 +187,7 @@ public:
static inline QFrameInfo endMarker()
{ return QFrameInfo(true); }
};
-Q_DECLARE_TYPEINFO(QFrameInfo, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QFrameInfo, Q_RELOCATABLE_TYPE);
class QMoviePrivate : public QObjectPrivate
{
@@ -247,20 +214,24 @@ public:
void _q_loadNextFrame();
void _q_loadNextFrame(bool starting);
- QImageReader *reader;
- int speed;
- QMovie::MovieState movieState;
+ QImageReader *reader = nullptr;
+
+ void setSpeed(int percentSpeed) { q_func()->setSpeed(percentSpeed); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QMoviePrivate, int, speed, &QMoviePrivate::setSpeed, 100)
+
+ QMovie::MovieState movieState = QMovie::NotRunning;
QRect frameRect;
QPixmap currentPixmap;
- int currentFrameNumber;
- int nextFrameNumber;
- int greatestFrameNumber;
- int nextDelay;
- int playCounter;
- qint64 initialDevicePos;
- QMovie::CacheMode cacheMode;
- bool haveReadAll;
- bool isFirstIteration;
+ int currentFrameNumber = -1;
+ int nextFrameNumber = 0;
+ int greatestFrameNumber = -1;
+ int nextDelay = 0;
+ int playCounter = -1;
+ qint64 initialDevicePos = 0;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QMoviePrivate, QMovie::CacheMode, cacheMode,
+ QMovie::CacheNone)
+ bool haveReadAll = false;
+ bool isFirstIteration = true;
QMap<int, QFrameInfo> frameMap;
QString absoluteFilePath;
@@ -270,10 +241,6 @@ public:
/*! \internal
*/
QMoviePrivate::QMoviePrivate(QMovie *qq)
- : reader(nullptr), speed(100), movieState(QMovie::NotRunning),
- currentFrameNumber(-1), nextFrameNumber(0), greatestFrameNumber(-1),
- nextDelay(0), playCounter(-1),
- cacheMode(QMovie::CacheNone), haveReadAll(false), isFirstIteration(true)
{
q_ptr = qq;
nextImageTimer.setSingleShot(true);
@@ -341,6 +308,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
return QFrameInfo(); // Invalid
}
+ // For an animated image format, the tradition is that QMovie calls read()
+ // until canRead() == false, because the number of frames may not be known
+ // in advance; but if we're abusing a multi-frame format as an animation,
+ // canRead() may remain true, and we need to stop after reading the maximum
+ // number of frames that the image provides.
+ const bool supportsAnimation = reader->supportsOption(QImageIOHandler::Animation);
+ const int stopAtFrame = supportsAnimation ? -1 : frameCount();
+
+ // For an animated image format, QImageIOHandler::nextImageDelay() should
+ // provide the time to wait until showing the next frame; but multi-frame
+ // formats are not expected to provide this value, so use 1000 ms by default.
+ const int nextFrameDelay = supportsAnimation ? reader->nextImageDelay() : 1000;
+
if (cacheMode == QMovie::CacheNone) {
if (frameNumber != currentFrameNumber+1) {
// Non-sequential frame access
@@ -370,8 +350,12 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
}
}
- if (reader->canRead()) {
+ qCDebug(lcImageIo, "CacheNone: read frame %d of %d", frameNumber, stopAtFrame);
+ if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) {
// reader says we can read. Attempt to actually read image
+ // But if it's a non-animated multi-frame format and we know the frame count, stop there.
+ if (stopAtFrame > 0)
+ reader->jumpToImage(frameNumber);
QImage anImage = reader->read();
if (anImage.isNull()) {
// Reading image failed.
@@ -379,7 +363,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
if (frameNumber > greatestFrameNumber)
greatestFrameNumber = frameNumber;
- return QFrameInfo(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay());
+ return QFrameInfo(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
} else if (frameNumber != 0) {
// We've read all frames now. Return an end marker
haveReadAll = true;
@@ -395,15 +379,19 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
if (frameNumber > greatestFrameNumber) {
// Frame hasn't been read from file yet. Try to do it
for (int i = greatestFrameNumber + 1; i <= frameNumber; ++i) {
- if (reader->canRead()) {
+ qCDebug(lcImageIo, "CacheAll: read frame %d of %d", frameNumber, stopAtFrame);
+ if (stopAtFrame > 0 ? (frameNumber < stopAtFrame) : reader->canRead()) {
// reader says we can read. Attempt to actually read image
+ // But if it's a non-animated multi-frame format and we know the frame count, stop there.
+ if (stopAtFrame > 0)
+ reader->jumpToImage(frameNumber);
QImage anImage = reader->read();
if (anImage.isNull()) {
// Reading image failed.
return QFrameInfo(); // Invalid
}
greatestFrameNumber = i;
- QFrameInfo info(QPixmap::fromImage(std::move(anImage)), reader->nextImageDelay());
+ QFrameInfo info(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
// Cache it!
frameMap.insert(i, info);
if (i == frameNumber) {
@@ -461,11 +449,7 @@ bool QMoviePrivate::next()
}
// Image and delay OK, update internal state
currentFrameNumber = nextFrameNumber++;
- QSize scaledSize = reader->scaledSize();
- if (scaledSize.isValid() && (scaledSize != info.pixmap.size()))
- currentPixmap = QPixmap::fromImage( info.pixmap.toImage().scaled(scaledSize) );
- else
- currentPixmap = info.pixmap;
+ currentPixmap = info.pixmap;
if (!speed)
return true;
@@ -928,7 +912,12 @@ void QMovie::setSpeed(int percentSpeed)
Q_D(QMovie);
if (!d->speed && d->movieState == Running)
d->nextImageTimer.start(nextFrameDelay());
- d->speed = percentSpeed;
+ if (percentSpeed != d->speed) {
+ d->speed = percentSpeed;
+ d->speed.notify();
+ } else {
+ d->speed.removeBindingUnlessInWrapper();
+ }
}
int QMovie::speed() const
@@ -937,6 +926,12 @@ int QMovie::speed() const
return d->speed;
}
+QBindable<int> QMovie::bindableSpeed()
+{
+ Q_D(QMovie);
+ return &d->speed;
+}
+
/*!
Starts the movie. QMovie will enter \l Running state, and start emitting
updated() and resized() as the movie progresses.
@@ -1022,7 +1017,7 @@ QList<QByteArray> QMovie::supportedFormats()
return !QImageReader(&buffer, format).supportsOption(QImageIOHandler::Animation);
};
- list.erase(std::remove_if(list.begin(), list.end(), doesntSupportAnimation), list.end());
+ list.removeIf(doesntSupportAnimation);
return list;
}
@@ -1059,6 +1054,12 @@ void QMovie::setCacheMode(CacheMode cacheMode)
d->cacheMode = cacheMode;
}
+QBindable<QMovie::CacheMode> QMovie::bindableCacheMode()
+{
+ Q_D(QMovie);
+ return &d->cacheMode;
+}
+
QT_END_NAMESPACE
#include "moc_qmovie.cpp"
diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h
index e13c528894..874e6189ba 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMOVIE_H
#define QMOVIE_H
@@ -64,8 +28,8 @@ class Q_GUI_EXPORT QMovie : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QMovie)
- Q_PROPERTY(int speed READ speed WRITE setSpeed)
- Q_PROPERTY(CacheMode cacheMode READ cacheMode WRITE setCacheMode)
+ Q_PROPERTY(int speed READ speed WRITE setSpeed BINDABLE bindableSpeed)
+ Q_PROPERTY(CacheMode cacheMode READ cacheMode WRITE setCacheMode BINDABLE bindableCacheMode)
public:
enum MovieState {
NotRunning,
@@ -115,12 +79,14 @@ public:
int currentFrameNumber() const;
int speed() const;
+ QBindable<int> bindableSpeed();
QSize scaledSize();
void setScaledSize(const QSize &size);
CacheMode cacheMode() const;
void setCacheMode(CacheMode mode);
+ QBindable<CacheMode> bindableCacheMode();
Q_SIGNALS:
void started();
diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp
index 224938bd9c..438305742c 100644
--- a/src/gui/image/qpaintengine_pic.cpp
+++ b/src/gui/image/qpaintengine_pic.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qpaintengine_p.h"
#include "private/qpainter_p.h"
diff --git a/src/gui/image/qpaintengine_pic_p.h b/src/gui/image/qpaintengine_pic_p.h
index c9e4b43197..44d0eb63db 100644
--- a/src/gui/image/qpaintengine_pic_p.h
+++ b/src/gui/image/qpaintengine_pic_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPAINTENGINE_PIC_P_H
#define QPAINTENGINE_PIC_P_H
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index d2ca2bbd22..da8c5ef1e5 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpicture.h"
#include <private/qpicture_p.h>
@@ -358,6 +322,8 @@ void QPicture::setBoundingRect(const QRect &r)
This function does exactly the same as QPainter::drawPicture()
with (x, y) = (0, 0).
+
+ \note The state of the painter isn't preserved by this function.
*/
bool QPicture::play(QPainter *painter)
@@ -848,6 +814,8 @@ bool QPicture::exec(QPainter *painter, QDataStream &s, int nrecords)
bool(ul & QPainter::Antialiasing));
painter->setRenderHint(QPainter::SmoothPixmapTransform,
bool(ul & QPainter::SmoothPixmapTransform));
+ painter->setRenderHint(QPainter::NonCosmeticBrushPatterns,
+ bool(ul & QPainter::NonCosmeticBrushPatterns));
break;
case QPicturePrivate::PdcSetCompositionMode:
s >> ul;
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index c3e622a1fe..bc8be6c4e9 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -1,49 +1,13 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPICTURE_H
#define QPICTURE_H
#include <QtGui/qtguiglobal.h>
#include <QtCore/qiodevice.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qstringlist.h>
-#include <QtCore/qsharedpointer.h>
#include <QtGui/qpaintdevice.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index 6e9510c77f..c512f49320 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPICTURE_P_H
#define QPICTURE_P_H
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index d8473001aa..89b8d5303b 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qglobal.h>
@@ -68,25 +32,31 @@
#include <qtgui_tracepoints_p.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+Q_TRACE_PARAM_REPLACE(Qt::AspectRatioMode, int);
+Q_TRACE_PARAM_REPLACE(Qt::TransformationMode, int);
+
+// MSVC 19.28 does show spurious warning "C4723: potential divide by 0" for code that divides
+// by height() in release builds. Anyhow, all the code paths in this file are only executed
+// for valid QPixmap's, where height() cannot be 0. Therefore disable the warning.
+QT_WARNING_DISABLE_MSVC(4723)
+
static bool qt_pixmap_thread_test()
{
if (Q_UNLIKELY(!QCoreApplication::instance())) {
qFatal("QPixmap: Must construct a QGuiApplication before a QPixmap");
return false;
}
-
- if (qApp->thread() != QThread::currentThread()) {
- bool fail = false;
- if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
- printf("Platform plugin does not support threaded pixmaps!\n");
- fail = true;
- }
- if (fail) {
- qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
- return false;
- }
+ if (QGuiApplicationPrivate::instance()
+ && qApp->thread() != QThread::currentThread()
+ && !QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) {
+ qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread on this platform");
+ return false;
}
return true;
}
@@ -633,7 +603,7 @@ qreal QPixmap::devicePixelRatio() const
high-DPI pixmap rather than a large pixmap
(see \l{Drawing High Resolution Versions of Pixmaps and Images}).
- \sa devicePixelRatio()
+ \sa devicePixelRatio(), deviceIndependentSize()
*/
void QPixmap::setDevicePixelRatio(qreal scaleFactor)
{
@@ -647,6 +617,23 @@ void QPixmap::setDevicePixelRatio(qreal scaleFactor)
data->setDevicePixelRatio(scaleFactor);
}
+/*!
+ Returns the size of the pixmap in device independent pixels.
+
+ This value should be used when using the pixmap size in user interface
+ size calculations.
+
+ The return value is equivalent to pixmap.size() / pixmap.devicePixelRatio().
+
+ \since 6.2
+*/
+QSizeF QPixmap::deviceIndependentSize() const
+{
+ if (!data)
+ return QSizeF(0, 0);
+ return QSizeF(data->width(), data->height()) / data->devicePixelRatio();
+}
+
#ifndef QT_NO_IMAGE_HEURISTIC_MASK
/*!
Creates and returns a heuristic mask for this pixmap.
@@ -728,9 +715,9 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (info.completeSuffix().isEmpty() || info.exists()) {
const bool inGuiThread = qApp->thread() == QThread::currentThread();
- QString key = QLatin1String("qt_pixmap")
+ QString key = "qt_pixmap"_L1
% info.absoluteFilePath()
- % HexString<uint>(info.lastModified().toSecsSinceEpoch())
+ % HexString<uint>(info.lastModified(QTimeZone::UTC).toSecsSinceEpoch())
% HexString<quint64>(info.size())
% HexString<uint>(data ? data->pixelType() : QPlatformPixmap::PixmapType);
@@ -885,6 +872,7 @@ void QPixmap::fill(const QColor &color)
// it will be filled with new pixel data anyway.
QPlatformPixmap *d = data->createCompatiblePlatformPixmap();
d->resize(data->width(), data->height());
+ d->setDevicePixelRatio(data->devicePixelRatio());
data = d;
}
data->fill(color);
@@ -1047,7 +1035,7 @@ bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags fla
Transformations}
*/
-QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaled: Pixmap is a null pixmap");
@@ -1085,7 +1073,7 @@ QPixmap QPixmap::scaled(const QSize& s, Qt::AspectRatioMode aspectMode, Qt::Tran
\sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap
Transformations}
*/
-QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaleWidth: Pixmap is a null pixmap");
@@ -1115,7 +1103,7 @@ QPixmap QPixmap::scaledToWidth(int w, Qt::TransformationMode mode) const
\sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap
Transformations}
*/
-QPixmap QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
+QPixmap Q_TRACE_INSTRUMENT(qtgui) QPixmap::scaledToHeight(int h, Qt::TransformationMode mode) const
{
if (isNull()) {
qWarning("QPixmap::scaleHeight: Pixmap is a null pixmap");
@@ -1292,8 +1280,9 @@ QPixmap QPixmap::transformed(const QTransform &transform,
QPixmap using the fromImage(). If this is too expensive an
operation, you can use QBitmap::fromImage() instead.
- To convert a QPixmap to and from HICON you can use the QtWinExtras
- functions QtWin::toHICON() and QtWin::fromHICON() respectively.
+ To convert a QPixmap to and from HICON you can use the
+ QImage::toHICON() and QImage::fromHICON() functions respectively
+ (after converting the QPixmap to a QImage, as explained above).
\section1 Pixmap Transformations
@@ -1422,7 +1411,7 @@ void QPixmap::detach()
return;
// QPixmap.data member may be QRuntimePlatformPixmap so use handle() function to get
- // the actual underlaying runtime pixmap data.
+ // the actual underlying runtime pixmap data.
QPlatformPixmap *pd = handle();
QPlatformPixmap::ClassId id = pd->classId();
if (id == QPlatformPixmap::RasterClass) {
@@ -1464,9 +1453,9 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImage(image, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
@@ -1491,9 +1480,9 @@ QPixmap QPixmap::fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags)
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageInPlace(image, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
@@ -1515,9 +1504,9 @@ QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionF
return QPixmap();
}
- QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
+ std::unique_ptr<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::PixmapType));
data->fromImageReader(imageReader, flags);
- return QPixmap(data.take());
+ return QPixmap(data.release());
}
/*!
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 42d4e27102..5be98be14d 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_H
#define QPIXMAP_H
@@ -44,8 +8,8 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qcolor.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h> // char*->QString conversion
-#include <QtCore/qsharedpointer.h>
#include <QtGui/qimage.h>
#include <QtGui/qtransform.h>
@@ -77,7 +41,7 @@ public:
QPixmap &operator=(const QPixmap &);
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QPixmap)
inline void swap(QPixmap &other) noexcept
- { qSwap(data, other.data); }
+ { data.swap(other.data); }
bool operator==(const QPixmap &) const = delete;
bool operator!=(const QPixmap &) const = delete;
@@ -101,6 +65,7 @@ public:
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
+ QSizeF deviceIndependentSize() const;
bool hasAlpha() const;
bool hasAlphaChannel() const;
@@ -164,7 +129,6 @@ private:
QPixmap(const QSize &s, int type);
void doInit(int, int, int);
- Q_DUMMY_COMPARISON_OPERATOR(QPixmap)
friend class QPlatformPixmap;
friend class QBitmap;
friend class QPaintDevice;
@@ -199,7 +163,7 @@ inline void QPixmap::scroll(int dx, int dy, int ax, int ay, int awidth, int ahei
inline bool QPixmap::loadFromData(const QByteArray &buf, const char *format,
Qt::ImageConversionFlags flags)
{
- return loadFromData(reinterpret_cast<const uchar *>(buf.constData()), buf.size(), format, flags);
+ return loadFromData(reinterpret_cast<const uchar *>(buf.constData()), uint(buf.size()), format, flags);
}
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 510a46e7b1..41563bf380 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpixmap_blitter_p.h"
diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h
index d39905f883..89928026a2 100644
--- a/src/gui/image/qpixmap_blitter_p.h
+++ b/src/gui/image/qpixmap_blitter_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_BLITTER_P_H
#define QPIXMAP_BLITTER_P_H
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 2732bbd197..6e10bdd562 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qpixmap.h"
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index fe2a1e581d..5f5c117002 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAP_RASTER_P_H
#define QPIXMAP_RASTER_P_H
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index aae4a1cbf4..fc601bccfc 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -1,44 +1,9 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qbitmap.h"
#include "qpixmap.h"
+#include <private/qpixmap_win_p.h>
#include <qpa/qplatformpixmap.h>
#include "qpixmap_raster_p.h"
@@ -199,7 +164,7 @@ static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *color
Q_ASSERT(DWORD(image.sizeInBytes()) == header.biSizeImage);
memcpy(image.bits(), data, header.biSizeImage);
if (format == QImage::Format_RGB888)
- image = image.rgbSwapped();
+ image = std::move(image).rgbSwapped();
break;
default:
Q_UNREACHABLE();
@@ -242,7 +207,7 @@ static HBITMAP qt_createIconMask(QImage bm)
return hbm;
}
-Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap)
+HBITMAP qt_createIconMask(const QBitmap &bitmap)
{
return qt_createIconMask(bitmap.toImage().convertToFormat(QImage::Format_Mono));
}
@@ -260,7 +225,7 @@ static inline QImage::Format format32(int hbitmapFormat)
return QImage::Format_ARGB32_Premultiplied;
}
-Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0)
+HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat)
{
if (imageIn.isNull())
return nullptr;
@@ -340,6 +305,7 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
return nullptr;
}
if (!pixels) {
+ DeleteObject(bitmap);
qErrnoWarning("%s, did not allocate pixel data", __FUNCTION__);
return nullptr;
}
@@ -359,7 +325,7 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
It is the caller's responsibility to free the \c HBITMAP data
after use.
- For usage with with standard GDI calls, such as \c BitBlt(), the image
+ For usage with standard GDI calls, such as \c BitBlt(), the image
should have the format QImage::Format_RGB32.
When using the resulting HBITMAP for the \c AlphaBlend() GDI function,
@@ -386,7 +352,7 @@ HBITMAP QImage::toHBITMAP() const
return qt_imageToWinHBITMAP(*this);
}
-Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0)
+HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat)
{
if (p.isNull())
return nullptr;
@@ -485,7 +451,7 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int
return copyImageData(info.bmiHeader, bmiColorTable256.bmiColors, data.data(), imageFormat);
}
-Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
{
QImage result = imageFromWinHBITMAP_DibSection(bitmap, hbitmapFormat);
if (result.isNull())
@@ -517,7 +483,7 @@ QImage QImage::fromHBITMAP(HBITMAP hbitmap)
return qt_imageFromWinHBITMAP(hbitmap);
}
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
+QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
{
return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat));
}
@@ -568,7 +534,7 @@ HICON QImage::toHICON(const QImage &mask) const
return hIcon;
}
-Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
+HICON qt_pixmapToWinHICON(const QPixmap &p)
{
QImage mask;
QBitmap maskBitmap = p.mask();
@@ -577,7 +543,7 @@ Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
return p.toImage().toHICON(mask);
}
-Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
+QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
if (image.isNull())
@@ -677,7 +643,7 @@ QImage QImage::fromHICON(HICON icon)
return image;
}
-Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
+QPixmap qt_pixmapFromWinHICON(HICON icon)
{
return QPixmap::fromImage(QImage::fromHICON(icon));
}
diff --git a/src/gui/image/qpixmap_win_p.h b/src/gui/image/qpixmap_win_p.h
new file mode 100644
index 0000000000..64abca3428
--- /dev/null
+++ b/src/gui/image/qpixmap_win_p.h
@@ -0,0 +1,38 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QPIXMAP_WIN_P_H
+#define QPIXMAP_WIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBitmap;
+class QImage;
+class QPixmap;
+
+Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
+Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0);
+Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0);
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p);
+Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h);
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
+
+QT_END_NAMESPACE
+
+#endif // QPIXMAP_WIN_P_H
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 26cc80b5b0..45c9743f93 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -1,43 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#define Q_TEST_QPIXMAPCACHE
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
#include "qpixmapcache.h"
#include "qobject.h"
#include "qdebug.h"
@@ -45,6 +8,8 @@
#include "qthread.h"
#include "qcoreapplication.h"
+using namespace std::chrono_literals;
+
QT_BEGIN_NAMESPACE
/*!
@@ -93,14 +58,14 @@ QT_BEGIN_NAMESPACE
static const int cache_limit_default = 10240; // 10 MB cache limit
-static inline int cost(const QPixmap &pixmap)
+static inline qsizetype cost(const QPixmap &pixmap)
{
- // make sure to do a 64bit calculation
- const qint64 costKb = static_cast<qint64>(pixmap.width()) *
- pixmap.height() * pixmap.depth() / (8 * 1024);
- const qint64 costMax = std::numeric_limits<int>::max();
+ // make sure to do a 64bit calculation; qsizetype might be smaller
+ const qint64 costKb = static_cast<qint64>(pixmap.width())
+ * pixmap.height() * pixmap.depth() / (8 * 1024);
+ const qint64 costMax = std::numeric_limits<qsizetype>::max();
// a small pixmap should have at least a cost of 1(kb)
- return static_cast<int>(qBound(1LL, costKb, costMax));
+ return static_cast<qsizetype>(qBound(1LL, costKb, costMax));
}
static inline bool qt_pixmapcache_thread_test()
@@ -219,7 +184,6 @@ public:
void timerEvent(QTimerEvent *) override;
bool insert(const QString& key, const QPixmap &pixmap, int cost);
QPixmapCache::Key insert(const QPixmap &pixmap, int cost);
- bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost);
bool remove(const QString &key);
bool remove(const QPixmapCache::Key &key);
@@ -239,7 +203,8 @@ public:
bool flushDetachedPixmaps(bool nt);
private:
- enum { soon_time = 10000, flush_time = 30000 };
+ static constexpr auto soon_time = 10s;
+ static constexpr auto flush_time = 30s;
int *keyArray;
int theid;
int ps;
@@ -253,9 +218,15 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qpixmapcache.moc"
QT_END_INCLUDE_NAMESPACE
-size_t qHash(const QPixmapCache::Key &k, size_t seed)
+/*!
+ size_t QPixmapCache::qHash(const Key &key, size_t seed = 0);
+ \since 6.6
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+size_t QPixmapCache::Key::hash(size_t seed) const noexcept
{
- return qHash(QPMCache::get(k)->key, seed);
+ return qHash(this->d ? this->d->key : 0, seed);
}
QPMCache::QPMCache()
@@ -286,24 +257,14 @@ QPMCache::~QPMCache()
*/
bool QPMCache::flushDetachedPixmaps(bool nt)
{
- int mc = maxCost();
- setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
+ auto mc = maxCost();
+ const qsizetype currentTotal = totalCost();
+ const qsizetype oldSize = size();
+ if (currentTotal)
+ setMaxCost(nt ? currentTotal * 3 / 4 : currentTotal - 1);
setMaxCost(mc);
ps = totalCost();
-
- bool any = false;
- QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
- while (it != cacheKeys.end()) {
- if (!contains(it.value())) {
- releaseKey(it.value());
- it = cacheKeys.erase(it);
- any = true;
- } else {
- ++it;
- }
- }
-
- return any;
+ return size() != oldSize;
}
void QPMCache::timerEvent(QTimerEvent *)
@@ -322,22 +283,14 @@ void QPMCache::timerEvent(QTimerEvent *)
QPixmap *QPMCache::object(const QString &key) const
{
- QPixmapCache::Key cacheKey = cacheKeys.value(key);
- if (!cacheKey.d || !cacheKey.d->isValid) {
- const_cast<QPMCache *>(this)->cacheKeys.remove(key);
- return nullptr;
- }
- QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(cacheKey);
- //We didn't find the pixmap in the cache, the key is not valid anymore
- if (!ptr) {
- const_cast<QPMCache *>(this)->cacheKeys.remove(key);
- }
- return ptr;
+ if (const auto it = cacheKeys.find(key); it != cacheKeys.cend())
+ return object(it.value());
+ return nullptr;
}
QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
{
- Q_ASSERT(key.d->isValid);
+ Q_ASSERT(key.isValid());
QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(key);
//We didn't find the pixmap in the cache, the key is not valid anymore
if (!ptr)
@@ -347,31 +300,24 @@ QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost)
{
- QPixmapCache::Key &cacheKey = cacheKeys[key];
//If for the same key we add already a pixmap we should delete it
- if (cacheKey.d)
- QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey);
-
- //we create a new key the old one has been removed
- cacheKey = createKey();
+ remove(key);
- bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
- if (success) {
- if (!theid) {
- theid = startTimer(flush_time);
- t = false;
- }
- } else {
- //Insertion failed we released the new allocated key
- cacheKeys.remove(key);
+ // this will create a new key; the old one has been removed
+ auto k = insert(pixmap, cost);
+ if (k.isValid()) {
+ k.d->stringKey = key;
+ cacheKeys[key] = std::move(k);
+ return true;
}
- return success;
+ return false;
}
QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
{
- QPixmapCache::Key cacheKey = createKey();
+ QPixmapCache::Key cacheKey = createKey(); // invalidated by ~QPixmapCacheEntry on failed insert
bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
+ Q_ASSERT(success || !cacheKey.isValid());
if (success) {
if (!theid) {
theid = startTimer(flush_time);
@@ -381,34 +327,10 @@ QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
return cacheKey;
}
-bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost)
-{
- Q_ASSERT(key.d->isValid);
- //If for the same key we had already an entry so we should delete the pixmap and use the new one
- QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(key);
-
- QPixmapCache::Key cacheKey = createKey();
-
- bool success = QCache<QPixmapCache::Key, QPixmapCacheEntry>::insert(cacheKey, new QPixmapCacheEntry(cacheKey, pixmap), cost);
- if (success) {
- if (!theid) {
- theid = startTimer(flush_time);
- t = false;
- }
- const_cast<QPixmapCache::Key&>(key) = cacheKey;
- }
- return success;
-}
-
bool QPMCache::remove(const QString &key)
{
- auto cacheKey = cacheKeys.constFind(key);
- //The key was not in the cache
- if (cacheKey == cacheKeys.constEnd())
- return false;
- const bool result = QCache<QPixmapCache::Key, QPixmapCacheEntry>::remove(cacheKey.value());
- cacheKeys.erase(cacheKey);
- return result;
+ const auto cacheKey = cacheKeys.take(key);
+ return cacheKey.isValid() && remove(cacheKey);
}
bool QPMCache::remove(const QPixmapCache::Key &key)
@@ -420,7 +342,7 @@ void QPMCache::resizeKeyArray(int size)
{
if (size <= keyArraySize || size == 0)
return;
- keyArray = q_check_ptr(reinterpret_cast<int *>(realloc(keyArray,
+ keyArray = q_check_ptr(static_cast<int *>(realloc(keyArray,
size * sizeof(int))));
for (int i = keyArraySize; i != size; ++i)
keyArray[i] = i + 1;
@@ -441,13 +363,18 @@ QPixmapCache::Key QPMCache::createKey()
void QPMCache::releaseKey(const QPixmapCache::Key &key)
{
- if (key.d->key > keyArraySize || key.d->key <= 0)
+ QPixmapCache::KeyData *keyData = key.d;
+ if (!keyData)
+ return;
+ if (!keyData->stringKey.isNull())
+ cacheKeys.remove(keyData->stringKey);
+ if (keyData->key > keyArraySize || keyData->key <= 0)
return;
- key.d->key--;
- keyArray[key.d->key] = freeKey;
- freeKey = key.d->key;
- key.d->isValid = false;
- key.d->key = 0;
+ keyData->key--;
+ keyArray[keyData->key] = freeKey;
+ freeKey = keyData->key;
+ keyData->isValid = false;
+ keyData->key = 0;
}
void QPMCache::clear()
@@ -457,10 +384,17 @@ void QPMCache::clear()
freeKey = 0;
keyArraySize = 0;
//Mark all keys as invalid
- QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
- for (int i = 0; i < keys.size(); ++i)
- keys.at(i).d->isValid = false;
+ const QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QPixmapCacheEntry>::keys();
+ for (const auto &key : keys) {
+ if (key.d)
+ key.d->isValid = false;
+ }
QCache<QPixmapCache::Key, QPixmapCacheEntry>::clear();
+ // Nothing left to flush; stop the timer
+ if (theid) {
+ killTimer(theid);
+ theid = 0;
+ }
}
QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key)
@@ -495,7 +429,7 @@ QPixmapCacheEntry::~QPixmapCacheEntry()
bool QPixmapCache::find(const QString &key, QPixmap *pixmap)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return false;
QPixmap *ptr = pm_cache()->object(key);
if (ptr && pixmap)
@@ -547,7 +481,7 @@ bool QPixmapCache::find(const Key &key, QPixmap *pixmap)
bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return false;
return pm_cache()->insert(key, pixmap, cost(pixmap));
}
@@ -574,24 +508,25 @@ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
return pm_cache()->insert(pixmap, cost(pixmap));
}
+#if QT_DEPRECATED_SINCE(6, 6)
/*!
+ \fn bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
+
+ \deprecated [6.6] Use \c{remove(key); key = insert(pixmap);} instead.
+
Replaces the pixmap associated with the given \a key with the \a pixmap
specified. Returns \c true if the \a pixmap has been correctly inserted into
the cache; otherwise returns \c false.
+ The passed \a key is updated to reference \a pixmap now. Other copies of \a
+ key, if any, still refer to the old pixmap, which is, however, removed from
+ the cache by this function.
+
\sa setCacheLimit(), insert()
\since 4.6
*/
-bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
-{
- if (!qt_pixmapcache_thread_test())
- return false;
- //The key is not valid anymore, a flush happened before probably
- if (!key.d || !key.d->isValid)
- return false;
- return pm_cache()->replace(key, pixmap, cost(pixmap));
-}
+#endif // QT_DEPRECATED_SINCE(6, 6)
/*!
Returns the cache limit (in kilobytes).
@@ -603,6 +538,8 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
int QPixmapCache::cacheLimit()
{
+ if (!qt_pixmapcache_thread_test())
+ return 0;
return pm_cache()->maxCost();
}
@@ -626,7 +563,7 @@ void QPixmapCache::setCacheLimit(int n)
*/
void QPixmapCache::remove(const QString &key)
{
- if (!qt_pixmapcache_thread_test())
+ if (key.isEmpty() || !qt_pixmapcache_thread_test())
return;
pm_cache()->remove(key);
}
@@ -664,13 +601,17 @@ void QPixmapCache::clear()
}
}
-void QPixmapCache::flushDetachedPixmaps()
+Q_AUTOTEST_EXPORT void qt_qpixmapcache_flush_detached_pixmaps() // for tst_qpixmapcache
{
+ if (!qt_pixmapcache_thread_test())
+ return;
pm_cache()->flushDetachedPixmaps(true);
}
-int QPixmapCache::totalUsed()
+Q_AUTOTEST_EXPORT int qt_qpixmapcache_qpixmapcache_total_used() // for tst_qpixmapcache
{
+ if (!qt_pixmapcache_thread_test())
+ return 0;
return (pm_cache()->totalCost()+1023) / 1024;
}
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 33021d1773..72ee1b797f 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAPCACHE_H
#define QPIXMAPCACHE_H
@@ -63,10 +27,14 @@ public:
{ return !operator==(key); }
Key &operator =(const Key &other);
- void swap(Key &other) noexcept { qSwap(d, other.d); }
+ void swap(Key &other) noexcept { qt_ptr_swap(d, other.d); }
bool isValid() const noexcept;
private:
+ friend size_t qHash(const QPixmapCache::Key &k, size_t seed = 0) noexcept
+ { return k.hash(seed); }
+ size_t hash(size_t seed) const noexcept;
+
KeyData *d;
friend class QPMCache;
friend class QPixmapCache;
@@ -78,18 +46,30 @@ public:
static bool find(const Key &key, QPixmap *pixmap);
static bool insert(const QString &key, const QPixmap &pixmap);
static Key insert(const QPixmap &pixmap);
+#if QT_DEPRECATED_SINCE(6, 6)
+ QT_DEPRECATED_VERSION_X_6_6("Use remove(key), followed by key = insert(pixmap).")
+ QT_GUI_INLINE_SINCE(6, 6)
static bool replace(const Key &key, const QPixmap &pixmap);
+#endif
static void remove(const QString &key);
static void remove(const Key &key);
static void clear();
-
-#ifdef Q_TEST_QPIXMAPCACHE
- static void flushDetachedPixmaps();
- static int totalUsed();
-#endif
};
Q_DECLARE_SHARED(QPixmapCache::Key)
+#if QT_DEPRECATED_SINCE(6, 6)
+#if QT_GUI_INLINE_IMPL_SINCE(6, 6)
+bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
+{
+ if (!key.isValid())
+ return false;
+ remove(key);
+ const_cast<Key&>(key) = insert(pixmap);
+ return key.isValid();
+}
+#endif // QT_GUI_INLINE_IMPL_SINCE(6, 6)
+#endif // QT_DEPRECATED_SINCE(6, 6)
+
QT_END_NAMESPACE
#endif // QPIXMAPCACHE_H
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
index fce2b2d9a1..43c4d9784c 100644
--- a/src/gui/image/qpixmapcache_p.h
+++ b/src/gui/image/qpixmapcache_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPIXMAPCACHE_P_H
#define QPIXMAPCACHE_P_H
@@ -59,8 +23,6 @@
QT_BEGIN_NAMESPACE
-size_t qHash(const QPixmapCache::Key &k, size_t seed = 0);
-
class QPixmapCache::KeyData
{
public:
@@ -69,6 +31,7 @@ public:
: isValid(other.isValid), key(other.key), ref(1) {}
~KeyData() {}
+ QString stringKey;
bool isValid;
int key;
int ref;
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index ea4243ba07..a297736095 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qplatformpixmap.h"
#include <qpa/qplatformintegration.h>
@@ -83,7 +47,7 @@ QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
QPlatformPixmap::~QPlatformPixmap()
{
- // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
+ // Sometimes the pixmap cleanup hooks will be called from derived classes, which will
// then set is_cached to false. For example, on X11 Qt GUI needs to delete the GLXPixmap
// or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
// otherwise some drivers will leak the GL surface. In this case, QX11PlatformPixmap will
@@ -101,10 +65,10 @@ QPlatformPixmap *QPlatformPixmap::createCompatiblePlatformPixmap() const
return d;
}
-static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, const QImage &image, Qt::ImageConversionFlags flags)
+static QImage makeBitmapCompliantIfNeeded(QPlatformPixmap *d, QImage image, Qt::ImageConversionFlags flags)
{
if (d->pixelType() == QPlatformPixmap::BitmapType) {
- QImage img = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ QImage img = std::move(image).convertToFormat(QImage::Format_MonoLSB, flags);
// make sure image.color(0) == Qt::color0 (white)
// and image.color(1) == Qt::color1 (black)
@@ -134,7 +98,7 @@ bool QPlatformPixmap::fromFile(const QString &fileName, const char *format,
QImage image = QImageReader(fileName, format).read();
if (image.isNull())
return false;
- fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
return !isNull();
}
@@ -146,7 +110,7 @@ bool QPlatformPixmap::fromData(const uchar *buf, uint len, const char *format, Q
QImage image = QImageReader(&b, format).read();
if (image.isNull())
return false;
- fromImage(makeBitmapCompliantIfNeeded(this, image, flags), flags);
+ fromImage(makeBitmapCompliantIfNeeded(this, std::move(image), flags), flags);
return !isNull();
}
@@ -168,9 +132,9 @@ QBitmap QPlatformPixmap::mask() const
if (!hasAlphaChannel())
return QBitmap();
- const QImage img = toImage();
+ QImage img = toImage();
bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
- const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
+ const QImage image = (shouldConvert ? std::move(img).convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
const int w = image.width();
const int h = image.height();
@@ -196,7 +160,7 @@ QBitmap QPlatformPixmap::mask() const
}
}
- return QBitmap::fromImage(mask);
+ return QBitmap::fromImage(std::move(mask));
}
void QPlatformPixmap::setMask(const QBitmap &mask)
@@ -204,7 +168,7 @@ void QPlatformPixmap::setMask(const QBitmap &mask)
QImage image = toImage();
if (mask.size().isEmpty()) {
if (image.depth() != 1) { // hw: ????
- image = image.convertToFormat(QImage::Format_RGB32);
+ image = std::move(image).convertToFormat(QImage::Format_RGB32);
}
} else {
const int w = image.width();
@@ -224,7 +188,7 @@ void QPlatformPixmap::setMask(const QBitmap &mask)
}
default: {
const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
- image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
for (int y = 0; y < h; ++y) {
const uchar *mscan = imageMask.scanLine(y);
QRgb *tscan = (QRgb *)image.scanLine(y);
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 9c7f5e5edf..be86bf8850 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPLATFORMPIXMAP_H
#define QPLATFORMPIXMAP_H
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index de913af320..615a36fa36 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -1,42 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qpnghandler_p.h"
@@ -81,6 +45,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
// avoid going through QImage::scanLine() which calls detach
@@ -101,7 +67,7 @@ public:
ReadingEnd,
Error
};
- // Defines the order of how the various ways of setting colorspace overrides eachother:
+ // Defines the order of how the various ways of setting colorspace overrides each other:
enum ColorSpaceState {
Undefined = 0,
GammaChrm = 1, // gAMA+cHRM chunks
@@ -199,7 +165,7 @@ void iod_read_fn(png_structp png_ptr, png_bytep data, png_size_t length)
QPngHandlerPrivate *d = (QPngHandlerPrivate *)png_get_io_ptr(png_ptr);
QIODevice *in = d->q->device();
- if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && (in->size() - in->pos()) < 4 && length == 4) {
+ if (d->state == QPngHandlerPrivate::ReadingEnd && !in->isSequential() && in->size() > 0 && (in->size() - in->pos()) < 4 && length == 4) {
// Workaround for certain malformed PNGs that lack the final crc bytes
uchar endcrc[4] = { 0xae, 0x42, 0x60, 0x82 };
memcpy(data, endcrc, 4);
@@ -500,7 +466,7 @@ static void read_image_scaled(QImage *outImage, png_structp png_ptr, png_infop i
extern "C" {
static void qt_png_warning(png_structp /*png_ptr*/, png_const_charp message)
{
- qCWarning(lcImageIo, "libpng warning: %s", message);
+ qCInfo(lcImageIo, "libpng warning: %s", message);
}
}
@@ -525,8 +491,8 @@ void QPngHandlerPrivate::readPngTexts(png_info *info)
value = QString::fromLatin1(text_ptr->text, int(text_ptr->text_length));
}
if (!description.isEmpty())
- description += QLatin1String("\n\n");
- description += key + QLatin1String(": ") + value.simplified();
+ description += "\n\n"_L1;
+ description += key + ": "_L1 + value.simplified();
readTexts.append(key);
readTexts.append(value);
text_ptr++;
@@ -588,10 +554,10 @@ bool QPngHandlerPrivate::readPngHeader()
#endif
png_uint_32 profLen;
png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen);
- colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
- if (!colorSpace.isValid()) {
- qCWarning(lcImageIo) << "QPngHandler: Failed to parse ICC profile";
- } else {
+ Q_UNUSED(name);
+ Q_UNUSED(compressionType);
+ if (profLen > 0) {
+ colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
QColorSpacePrivate *csD = QColorSpacePrivate::get(colorSpace);
if (csD->description.isEmpty())
csD->description = QString::fromLatin1((const char *)name);
@@ -627,10 +593,10 @@ bool QPngHandlerPrivate::readPngHeader()
}
if (primaries.areValid()) {
colorSpace = QColorSpace(primaries.whitePoint, primaries.redPoint, primaries.greenPoint, primaries.bluePoint,
- QColorSpace::TransferFunction::Gamma, fileGamma);
+ QColorSpace::TransferFunction::Gamma, 1.0f / fileGamma);
} else {
colorSpace = QColorSpace(QColorSpace::Primaries::SRgb,
- QColorSpace::TransferFunction::Gamma, fileGamma);
+ QColorSpace::TransferFunction::Gamma, 1.0f / fileGamma);
}
colorSpaceState = GammaChrm;
}
@@ -832,7 +798,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
int i = 0;
while (it != text.constEnd()) {
text_ptr[i].key = qstrdup(QStringView{it.key()}.left(79).toLatin1().constData());
- bool noCompress = (it.value().length() < 40);
+ bool noCompress = (it.value().size() < 40);
#ifdef PNG_iTXt_SUPPORTED
bool needsItxt = false;
@@ -960,15 +926,15 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const
color_type, 0, 0, 0); // sets #channels
#ifdef PNG_iCCP_SUPPORTED
- if (image.colorSpace().isValid()) {
- QColorSpace cs = image.colorSpace();
- // Support the old gamma making it override transferfunction.
- if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma))
- cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
- QByteArray iccProfileName = QColorSpacePrivate::get(cs)->description.toLatin1();
+ QColorSpace cs = image.colorSpace();
+ // Support the old gamma making it override transferfunction (if possible)
+ if (cs.isValid() && gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma))
+ cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
+ QByteArray iccProfile = cs.iccProfile();
+ if (!iccProfile.isEmpty()) {
+ QByteArray iccProfileName = cs.description().toLatin1();
if (iccProfileName.isEmpty())
iccProfileName = QByteArrayLiteral("Custom");
- QByteArray iccProfile = cs.iccProfile();
png_set_iCCP(png_ptr, info_ptr,
#if PNG_LIBPNG_VER < 10500
iccProfileName.data(), PNG_COMPRESSION_TYPE_BASE, iccProfile.data(),
@@ -976,7 +942,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const
iccProfileName.constData(), PNG_COMPRESSION_TYPE_BASE,
(png_const_bytep)iccProfile.constData(),
#endif
- iccProfile.length());
+ iccProfile.size());
} else
#endif
if (gamma != 0.0) {
diff --git a/src/gui/image/qpnghandler.pri b/src/gui/image/qpnghandler.pri
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/gui/image/qpnghandler.pri
+++ /dev/null
diff --git a/src/gui/image/qpnghandler_p.h b/src/gui/image/qpnghandler_p.h
index 9e12d2d081..fa4a7788f7 100644
--- a/src/gui/image/qpnghandler_p.h
+++ b/src/gui/image/qpnghandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPNGHANDLER_P_H
#define QPNGHANDLER_P_H
diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp
index 71dbefe354..3a4af46195 100644
--- a/src/gui/image/qppmhandler.cpp
+++ b/src/gui/image/qppmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qppmhandler_p.h"
@@ -47,8 +11,8 @@
#include <qloggingcategory.h>
#include <qrgba64.h>
#include <qvariant.h>
-
-#include <ctype.h>
+#include <private/qlocale_p.h>
+#include <private/qtools_p.h>
QT_BEGIN_NAMESPACE
@@ -68,7 +32,7 @@ static void discard_pbm_line(QIODevice *d)
} while (res > 0 && buf[res-1] != '\n');
}
-static int read_pbm_int(QIODevice *d)
+static int read_pbm_int(QIODevice *d, bool *ok, int maxDigits = -1)
{
char c;
int val = -1;
@@ -77,7 +41,7 @@ static int read_pbm_int(QIODevice *d)
for (;;) {
if (!d->getChar(&c)) // end of file
break;
- digit = isdigit((uchar) c);
+ digit = QtMiscUtils::isAsciiDigit(c);
if (val != -1) {
if (digit) {
const int cValue = c - '0';
@@ -86,6 +50,8 @@ static int read_pbm_int(QIODevice *d)
} else {
hasOverflow = true;
}
+ if (maxDigits > 0 && --maxDigits == 0)
+ break;
continue;
} else {
if (c == '#') // comment
@@ -95,13 +61,17 @@ static int read_pbm_int(QIODevice *d)
}
if (digit) // first digit
val = c - '0';
- else if (isspace((uchar) c))
+ else if (ascii_isspace(c))
continue;
else if (c == '#')
discard_pbm_line(d);
else
break;
+ if (maxDigits > 0 && --maxDigits == 0)
+ break;
}
+ if (val < 0)
+ *ok = false;
return hasOverflow ? -1 : val;
}
@@ -111,23 +81,24 @@ static bool read_pbm_header(QIODevice *device, char& type, int& w, int& h, int&
if (device->read(buf, 3) != 3) // read P[1-6]<white-space>
return false;
- if (!(buf[0] == 'P' && isdigit((uchar) buf[1]) && isspace((uchar) buf[2])))
+ if (!(buf[0] == 'P' && QtMiscUtils::isAsciiDigit(buf[1]) && ascii_isspace(buf[2])))
return false;
type = buf[1];
if (type < '1' || type > '6')
return false;
- w = read_pbm_int(device); // get image width
- h = read_pbm_int(device); // get image height
+ bool ok = true;
+ w = read_pbm_int(device, &ok); // get image width
+ h = read_pbm_int(device, &ok); // get image height
if (type == '1' || type == '4')
mcc = 1; // ignore max color component
else
- mcc = read_pbm_int(device); // get max color component
+ mcc = read_pbm_int(device, &ok); // get max color component
- if (w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
- return false; // weird P.M image
+ if (!ok || w <= 0 || w > 32767 || h <= 0 || h > 32767 || mcc <= 0 || mcc > 0xffff)
+ return false; // weird P.M image
return true;
}
@@ -235,18 +206,18 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
} else { // read ascii data
uchar *p;
qsizetype n;
- char buf;
- for (y = 0; (y < h) && (device->peek(&buf, 1) == 1); y++) {
+ bool ok = true;
+ for (y = 0; y < h && ok; y++) {
p = outImage->scanLine(y);
n = pbm_bpl;
if (nbits == 1) {
int b;
int bitsLeft = w;
- while (n--) {
+ while (n-- && ok) {
b = 0;
for (int i=0; i<8; i++) {
if (i < bitsLeft)
- b = (b << 1) | (read_pbm_int(device) & 1);
+ b = (b << 1) | (read_pbm_int(device, &ok, 1) & 1);
else
b = (b << 1) | (0 & 1); // pad it our self if we need to
}
@@ -255,36 +226,38 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
}
} else if (nbits == 8) {
if (mcc == 255) {
- while (n--) {
- *p++ = read_pbm_int(device);
+ while (n-- && ok) {
+ *p++ = read_pbm_int(device, &ok);
}
} else {
- while (n--) {
- *p++ = (read_pbm_int(device) & 0xffff) * 255 / mcc;
+ while (n-- && ok) {
+ *p++ = (read_pbm_int(device, &ok) & 0xffff) * 255 / mcc;
}
}
} else { // 32 bits
n /= 4;
int r, g, b;
if (mcc == 255) {
- while (n--) {
- r = read_pbm_int(device);
- g = read_pbm_int(device);
- b = read_pbm_int(device);
+ while (n-- && ok) {
+ r = read_pbm_int(device, &ok);
+ g = read_pbm_int(device, &ok);
+ b = read_pbm_int(device, &ok);
*((QRgb*)p) = qRgb(r, g, b);
p += 4;
}
} else {
- while (n--) {
- r = read_pbm_int(device);
- g = read_pbm_int(device);
- b = read_pbm_int(device);
+ while (n-- && ok) {
+ r = read_pbm_int(device, &ok);
+ g = read_pbm_int(device, &ok);
+ b = read_pbm_int(device, &ok);
*((QRgb*)p) = scale_pbm_color(mcc, r, g, b);
p += 4;
}
}
}
}
+ if (!ok)
+ return false;
}
if (format == QImage::Format_Mono) {
@@ -296,13 +269,12 @@ static bool read_pbm_body(QIODevice *device, char type, int w, int h, int mcc, Q
return true;
}
-static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QByteArray &sourceFormat)
+static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, QByteArrayView sourceFormat)
{
QByteArray str;
QImage image = sourceImage;
- QByteArray format = sourceFormat;
+ const QByteArrayView format = sourceFormat.left(3); // ignore RAW part
- format = format.left(3); // ignore RAW part
bool gray = format == "pgm";
if (format == "pbm") {
@@ -353,7 +325,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
switch (image.depth()) {
case 1: {
str.insert(1, '4');
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
w = (w+7)/8;
for (uint y=0; y<h; y++) {
@@ -367,12 +339,12 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case 8: {
str.insert(1, gray ? '5' : '6');
str.append("255\n");
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
qsizetype bpl = qsizetype(w) * (gray ? 1 : 3);
uchar *buf = new uchar[bpl];
if (image.format() == QImage::Format_Indexed8) {
- QList<QRgb> color = image.colorTable();
+ const QList<QRgb> color = image.colorTable();
for (uint y=0; y<h; y++) {
const uchar *b = image.constScanLine(y);
uchar *p = buf;
@@ -420,7 +392,7 @@ static bool write_pbm_image(QIODevice *out, const QImage &sourceImage, const QBy
case 32: {
str.insert(1, '6');
str.append("255\n");
- if (out->write(str, str.length()) != str.length())
+ if (out->write(str, str.size()) != str.size())
return false;
qsizetype bpl = qsizetype(w) * 3;
uchar *buf = new uchar[bpl];
diff --git a/src/gui/image/qppmhandler_p.h b/src/gui/image/qppmhandler_p.h
index f2faf93984..49663ebc53 100644
--- a/src/gui/image/qppmhandler_p.h
+++ b/src/gui/image/qppmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QPPMHANDLER_P_H
#define QPPMHANDLER_P_H
diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp
index 9c324aeeb9..8206fe3b29 100644
--- a/src/gui/image/qxbmhandler.cpp
+++ b/src/gui/image/qxbmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <qplatformdefs.h>
#include "private/qxbmhandler_p.h"
@@ -46,12 +10,14 @@
#include <qiodevice.h>
#include <qloggingcategory.h>
#include <qvariant.h>
+#include <private/qtools_p.h>
#include <stdio.h>
-#include <ctype.h>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
/*****************************************************************************
@@ -60,8 +26,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
static inline int hex2byte(char *p)
{
- return ((isdigit((uchar) *p) ? *p - '0' : toupper((uchar) *p) - 'A' + 10) << 4) |
- (isdigit((uchar) *(p+1)) ? *(p+1) - '0' : toupper((uchar) *(p+1)) - 'A' + 10);
+ return QtMiscUtils::fromHex(p[0]) * 16 | QtMiscUtils::fromHex(p[1]);
}
static bool read_xbm_header(QIODevice *device, int& w, int& h)
@@ -91,11 +56,9 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
}
auto parseDefine = [] (const char *buf, int len) -> int {
- auto isAsciiLetterOrNumber = [] (char ch) -> bool {
- return (ch >= '0' && ch <= '9') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= 'a' && ch <= 'z') ||
- ch == '_' || ch == '.';
+ auto checkChar = [] (char ch) -> bool {
+ return isAsciiLetterOrNumber(ch)
+ || ch == '_' || ch == '.';
};
auto isAsciiSpace = [] (char ch) -> bool {
return ch == ' ' || ch == '\t';
@@ -107,7 +70,7 @@ static bool read_xbm_header(QIODevice *device, int& w, int& h)
int index = defineLen;
while (buf[index] && isAsciiSpace(buf[index]))
++index;
- while (buf[index] && isAsciiLetterOrNumber(buf[index]))
+ while (buf[index] && checkChar(buf[index]))
++index;
while (buf[index] && isAsciiSpace(buf[index]))
++index;
@@ -165,9 +128,10 @@ static bool read_xbm_body(QIODevice *device, int w, int h, QImage *outImage)
while (y < h) { // for all encoded bytes...
if (p && p < (buf + readBytes - 3)) { // p = "0x.."
- if (!isxdigit(p[2]) || !isxdigit(p[3]))
+ const int byte = hex2byte(p + 2);
+ if (byte < 0) // non-hex char encountered
return false;
- *b++ = hex2byte(p+2);
+ *b++ = byte;
p += 2;
if (++x == w && ++y < h) {
b = outImage->scanLine(y);
@@ -200,7 +164,7 @@ static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const
int h = image.height();
int i;
QString s = fileName; // get file base name
- int msize = s.length() + 100;
+ int msize = s.size() + 100;
char *buf = new char[msize];
qsnprintf(buf, msize, "#define %s_width %d\n", s.toUtf8().data(), w);
diff --git a/src/gui/image/qxbmhandler_p.h b/src/gui/image/qxbmhandler_p.h
index db5f352d46..6a04faa42b 100644
--- a/src/gui/image/qxbmhandler_p.h
+++ b/src/gui/image/qxbmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXBMHANDLER_P_H
#define QXBMHANDLER_P_H
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 7b545614a7..50f9f035a6 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "private/qxpmhandler_p.h"
@@ -50,11 +14,16 @@
#include <qvariant.h>
#include <private/qcolor_p.h>
+#include <private/qduplicatetracker_p.h> // for easier std::pmr detection
+#include <private/qtools_p.h>
#include <algorithm>
+#include <array>
QT_BEGIN_NAMESPACE
+using namespace QtMiscUtils;
+
Q_DECLARE_LOGGING_CATEGORY(lcImageIo)
static quint64 xpmHash(const QString &str)
@@ -752,15 +721,12 @@ inline bool operator<(const char *name, const XPMRGBData &data)
inline bool operator<(const XPMRGBData &data, const char *name)
{ return qstrcmp(data.name, name) < 0; }
-static inline bool qt_get_named_xpm_rgb(const char *name_no_space, QRgb *rgb)
+static inline std::optional<QRgb> qt_get_named_xpm_rgb(const char *name_no_space)
{
const XPMRGBData *r = std::lower_bound(xpmRgbTbl, xpmRgbTbl + xpmRgbTblSize, name_no_space);
- if ((r != xpmRgbTbl + xpmRgbTblSize) && !(name_no_space < *r)) {
- *rgb = r->value;
- return true;
- } else {
- return false;
- }
+ if ((r != xpmRgbTbl + xpmRgbTblSize) && !(name_no_space < *r))
+ return r->value;
+ return {};
}
/*****************************************************************************
@@ -770,18 +736,16 @@ static QString fbname(const QString &fileName) // get file basename (sort of)
{
QString s = fileName;
if (!s.isEmpty()) {
- int i = qMax(s.lastIndexOf(QLatin1Char('/')), s.lastIndexOf(QLatin1Char('\\')));
+ int i = qMax(s.lastIndexOf(u'/'), s.lastIndexOf(u'\\'));
if (i < 0)
i = 0;
- auto isAsciiLetterOrNumber = [](QChar ch) -> bool {
- return (ch.unicode() >= '0' && ch.unicode() <= '9') ||
- (ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
- (ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
- ch.unicode() == '_';
+ auto checkChar = [](QChar ch) -> bool {
+ uchar uc = ch.unicode();
+ return isAsciiLetterOrNumber(uc) || uc == '_';
};
int start = -1;
- for (; i < s.length(); ++i) {
- if (isAsciiLetterOrNumber(s.at(i))) {
+ for (; i < s.size(); ++i) {
+ if (checkChar(s.at(i))) {
start = i;
} else if (start > 0)
break;
@@ -929,25 +893,25 @@ static bool read_xpm_body(
int transparentColor = currentColor;
if (ncols <= 256) {
image.setColor(transparentColor, 0);
- colorMap.insert(xpmHash(QLatin1String(index.constData())), transparentColor);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), transparentColor);
} else {
- colorMap.insert(xpmHash(QLatin1String(index.constData())), 0);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), 0);
}
} else {
- QRgb c_rgb;
- if (((buf.length()-1) % 3) && (buf[0] == '#')) {
- buf.truncate(((buf.length()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
+ QRgb c_rgb = 0;
+ if (((buf.size()-1) % 3) && (buf[0] == '#')) {
+ buf.truncate(((buf.size()-1) / 4 * 3) + 1); // remove alpha channel left by imagemagick
}
if (buf[0] == '#') {
- qt_get_hex_rgb(buf, &c_rgb);
+ c_rgb = qt_get_hex_rgb(buf).value_or(0);
} else {
- qt_get_named_xpm_rgb(buf, &c_rgb);
+ c_rgb = qt_get_named_xpm_rgb(buf).value_or(0);
}
if (ncols <= 256) {
image.setColor(currentColor, 0xff000000 | c_rgb);
- colorMap.insert(xpmHash(QLatin1String(index.constData())), currentColor);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), currentColor);
} else {
- colorMap.insert(xpmHash(QLatin1String(index.constData())), 0xff000000 | c_rgb);
+ colorMap.insert(xpmHash(QLatin1StringView(index.constData())), 0xff000000 | c_rgb);
}
}
}
@@ -969,7 +933,7 @@ static bool read_xpm_body(
if (image.depth() == 8) {
uchar *p = image.scanLine(y);
uchar *d = (uchar *)buf.data();
- uchar *end = d + buf.length();
+ uchar *end = d + buf.size();
int x;
if (cpp == 1) {
char b[2];
@@ -995,7 +959,7 @@ static bool read_xpm_body(
} else {
QRgb *p = (QRgb*)image.scanLine(y);
uchar *d = (uchar *)buf.data();
- uchar *end = d + buf.length();
+ uchar *end = d + buf.size();
int x;
char b[16];
b[cpp] = '\0';
@@ -1063,15 +1027,23 @@ bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source,
return read_xpm_body(device, source, index, state, cpp, ncols, w, h, image);
}
-static const char* xpm_color_name(int cpp, int index)
+namespace {
+template <size_t N>
+struct CharBuffer : std::array<char, N>
+{
+ CharBuffer() {} // avoid value-initializing the whole array
+};
+}
+
+static const char* xpm_color_name(int cpp, int index, CharBuffer<5> && returnable = {})
{
- static char returnable[5];
static const char code[] = ".#abcdefghijklmnopqrstuvwxyzABCD"
"EFGHIJKLMNOPQRSTUVWXYZ0123456789";
// cpp is limited to 4 and index is limited to 64^cpp
if (cpp > 1) {
if (cpp > 2) {
if (cpp > 3) {
+ returnable[4] = '\0';
returnable[3] = code[index % 64];
index /= 64;
} else
@@ -1091,7 +1063,7 @@ static const char* xpm_color_name(int cpp, int index)
returnable[1] = '\0';
returnable[0] = code[index];
- return returnable;
+ return returnable.data();
}
@@ -1107,18 +1079,25 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
else
image = sourceImage;
- QMap<QRgb, int> colorMap;
+#ifdef __cpp_lib_memory_resource
+ char buffer[1024];
+ std::pmr::monotonic_buffer_resource res{&buffer, sizeof buffer};
+ std::pmr::map<QRgb, int> colorMap(&res);
+#else
+ std::map<QRgb, int> colorMap;
+#endif
- int w = image.width(), h = image.height(), ncolors = 0;
- int x, y;
+ const int w = image.width();
+ const int h = image.height();
+ int ncolors = 0;
// build color table
- for(y=0; y<h; y++) {
+ for (int y = 0; y < h; ++y) {
const QRgb *yp = reinterpret_cast<const QRgb *>(image.constScanLine(y));
- for(x=0; x<w; x++) {
- QRgb color = *(yp + x);
- if (!colorMap.contains(color))
- colorMap.insert(color, ncolors++);
+ for (int x = 0; x < w; ++x) {
+ const auto [it, inserted] = colorMap.try_emplace(yp[x], ncolors);
+ if (inserted)
+ ++ncolors;
}
}
@@ -1128,8 +1107,11 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
++cpp;
// limit to 4 characters per pixel
// 64^4 colors is enough for a 4096x4096 image
- if (cpp > 4)
- break;
+ if (cpp > 4) {
+ qCWarning(lcImageIo, "Qt does not support writing XPM images with more than "
+ "64^4 colors (requested: %d colors).", ncolors);
+ return false;
+ }
}
// write header
@@ -1139,36 +1121,21 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
<< '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
// write palette
- QMap<QRgb, int>::Iterator c = colorMap.begin();
- while (c != colorMap.end()) {
- QRgb color = c.key();
+ for (const auto &[color, index] : colorMap) {
const QString line = image.format() != QImage::Format_RGB32 && !qAlpha(color)
- ? QString::asprintf("\"%s c None\"", xpm_color_name(cpp, *c))
- : QString::asprintf("\"%s c #%02x%02x%02x\"", xpm_color_name(cpp, *c),
+ ? QString::asprintf("\"%s c None\"", xpm_color_name(cpp, index))
+ : QString::asprintf("\"%s c #%02x%02x%02x\"", xpm_color_name(cpp, index),
qRed(color), qGreen(color), qBlue(color));
- ++c;
s << ',' << Qt::endl << line;
}
// write pixels, limit to 4 characters per pixel
- QByteArray line;
- for(y=0; y<h; y++) {
- line.clear();
+ for (int y = 0; y < h; ++y) {
+ s << ',' << Qt::endl << '\"';
const QRgb *yp = reinterpret_cast<const QRgb *>(image.constScanLine(y));
- for(x=0; x<w; x++) {
- int color = (int)(*(yp + x));
- const QByteArray chars(xpm_color_name(cpp, colorMap[color]));
- line.append(chars[0]);
- if (cpp > 1) {
- line.append(chars[1]);
- if (cpp > 2) {
- line.append(chars[2]);
- if (cpp > 3)
- line.append(chars[3]);
- }
- }
- }
- s << ',' << Qt::endl << '\"' << line << '\"';
+ for (int x = 0; x < w; ++x)
+ s << xpm_color_name(cpp, colorMap[yp[x]]);
+ s << '\"';
}
s << "};" << Qt::endl;
return (s.status() == QTextStream::Ok);
diff --git a/src/gui/image/qxpmhandler_p.h b/src/gui/image/qxpmhandler_p.h
index 646e8df69e..c55653f3ec 100644
--- a/src/gui/image/qxpmhandler_p.h
+++ b/src/gui/image/qxpmhandler_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QXPMHANDLER_P_H
#define QXPMHANDLER_P_H