summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/qbitmap.h2
-rw-r--r--src/gui/image/qbmphandler.cpp4
-rw-r--r--src/gui/image/qicon.cpp42
-rw-r--r--src/gui/image/qicon.h7
-rw-r--r--src/gui/image/qicon_p.h22
-rw-r--r--src/gui/image/qiconengineplugin.h2
-rw-r--r--src/gui/image/qiconloader.cpp102
-rw-r--r--src/gui/image/qiconloader_p.h30
-rw-r--r--src/gui/image/qimage.cpp113
-rw-r--r--src/gui/image/qimage.h41
-rw-r--r--src/gui/image/qimage_conversions.cpp64
-rw-r--r--src/gui/image/qimage_darwin.mm2
-rw-r--r--src/gui/image/qimage_p.h4
-rw-r--r--src/gui/image/qimageiohandler.h2
-rw-r--r--src/gui/image/qimagereader.cpp11
-rw-r--r--src/gui/image/qimagewriter.cpp10
-rw-r--r--src/gui/image/qimagewriter.h3
-rw-r--r--src/gui/image/qmovie.cpp48
-rw-r--r--src/gui/image/qmovie.h8
-rw-r--r--src/gui/image/qpaintengine_pic_p.h22
-rw-r--r--src/gui/image/qpicture.cpp6
-rw-r--r--src/gui/image/qpicture.h26
-rw-r--r--src/gui/image/qpictureformatplugin.h2
-rw-r--r--src/gui/image/qpixmap.cpp71
-rw-r--r--src/gui/image/qpixmap.h22
-rw-r--r--src/gui/image/qpixmap_blitter.cpp7
-rw-r--r--src/gui/image/qpixmap_blitter_p.h22
-rw-r--r--src/gui/image/qpixmap_raster_p.h38
-rw-r--r--src/gui/image/qpixmapcache.cpp2
-rw-r--r--src/gui/image/qpixmapcache.h2
-rw-r--r--src/gui/image/qplatformpixmap.cpp76
-rw-r--r--src/gui/image/qplatformpixmap.h8
-rw-r--r--src/gui/image/qxpmhandler.cpp5
33 files changed, 559 insertions, 267 deletions
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h
index def59b3f89..6a8c8b3457 100644
--- a/src/gui/image/qbitmap.h
+++ b/src/gui/image/qbitmap.h
@@ -55,7 +55,7 @@ public:
QBitmap(const QPixmap &);
QBitmap(int w, int h);
explicit QBitmap(const QSize &);
- explicit QBitmap(const QString &fileName, const char *format = Q_NULLPTR);
+ explicit QBitmap(const QString &fileName, const char *format = nullptr);
// ### Qt 6: don't inherit QPixmap
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QBitmap(const QBitmap &other) : QPixmap(other) {}
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 703c5c0f31..587f375ce7 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -49,10 +49,10 @@ QT_BEGIN_NAMESPACE
static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels
{
- int i;
+ qsizetype i;
if (image->depth() == 1 && image->colorCount() == 2) {
uint *p = (uint *)image->bits();
- int nbytes = image->byteCount();
+ qsizetype nbytes = static_cast<qsizetype>(image->sizeInBytes());
for (i=0; i<nbytes/4; i++) {
*p = ~*p;
p++;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index fa4b4e01af..32fa9e75ac 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1158,6 +1158,36 @@ QStringList QIcon::themeSearchPaths()
}
/*!
+ \since 5.11
+
+ Returns the fallback search paths for icons.
+
+ The default value will depend on the platform.
+
+ \sa setFallbackSearchPaths(), themeSearchPaths()
+*/
+QStringList QIcon::fallbackSearchPaths()
+{
+ return QIconLoader::instance()->fallbackSearchPaths();
+}
+
+/*!
+ \since 5.11
+
+ Sets the fallback search paths for icons to \a paths.
+
+ \note To add some path without replacing existing ones:
+
+ \snippet code/src_gui_image_qicon.cpp 5
+
+ \sa fallbackSearchPaths(), setThemeSearchPaths()
+*/
+void QIcon::setFallbackSearchPaths(const QStringList &paths)
+{
+ QIconLoader::instance()->setFallbackSearchPaths(paths);
+}
+
+/*!
\since 4.6
Sets the current icon theme to \a name.
@@ -1216,7 +1246,10 @@ QString QIcon::themeName()
the lookup. These caches can be generated using gtk-update-icon-cache:
\l{https://developer.gnome.org/gtk3/stable/gtk-update-icon-cache.html}.
- \sa themeName(), setThemeName(), themeSearchPaths()
+ \note If an icon can't be found in the current theme, then it will be
+ searched in fallbackSearchPaths() as an unthemed icon.
+
+ \sa themeName(), setThemeName(), themeSearchPaths(), fallbackSearchPaths()
*/
QIcon QIcon::fromTheme(const QString &name)
{
@@ -1469,8 +1502,13 @@ QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRati
return baseFileName;
int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.'));
- if (dotIndex == -1) /* no dot */
+ if (dotIndex == -1) { /* no dot */
dotIndex = baseFileName.size(); /* append */
+ } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == QLatin1Char('9')
+ && baseFileName[dotIndex - 2] == QLatin1Char('.')) {
+ // 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"));
diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h
index 40d3e92af9..653ba6fda4 100644
--- a/src/gui/image/qicon.h
+++ b/src/gui/image/qicon.h
@@ -63,7 +63,7 @@ public:
#ifdef Q_COMPILER_RVALUE_REFS
QIcon(QIcon &&other) Q_DECL_NOEXCEPT
: d(other.d)
- { other.d = Q_NULLPTR; }
+ { other.d = nullptr; }
#endif
explicit QIcon(const QString &fileName); // file or resource name
explicit QIcon(QIconEngine *engine);
@@ -118,6 +118,9 @@ public:
static QStringList themeSearchPaths();
static void setThemeSearchPaths(const QStringList &searchpath);
+ static QStringList fallbackSearchPaths();
+ static void setFallbackSearchPaths(const QStringList &paths);
+
static QString themeName();
static void setThemeName(const QString &path);
@@ -147,7 +150,7 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QIcon &);
#endif
Q_GUI_EXPORT QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio,
- qreal *sourceDevicePixelRatio = Q_NULLPTR);
+ qreal *sourceDevicePixelRatio = nullptr);
QT_END_NAMESPACE
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index aa358e88af..e384ff9e49 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -112,18 +112,18 @@ public:
QPixmapIconEngine();
QPixmapIconEngine(const QPixmapIconEngine &);
~QPixmapIconEngine();
- void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QPixmapIconEngineEntry *bestMatch(const QSize &size, QIcon::Mode mode, QIcon::State state, bool sizeOnly);
- QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
-
- QString key() const Q_DECL_OVERRIDE;
- QIconEngine *clone() const Q_DECL_OVERRIDE;
- bool read(QDataStream &in) Q_DECL_OVERRIDE;
- bool write(QDataStream &out) const Q_DECL_OVERRIDE;
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
+ QSize actualSize(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;
+ void virtual_hook(int id, void *data) override;
private:
QPixmapIconEngineEntry *tryMatch(const QSize &size, QIcon::Mode mode, QIcon::State state);
diff --git a/src/gui/image/qiconengineplugin.h b/src/gui/image/qiconengineplugin.h
index 7a01d3731c..f2a1c0107a 100644
--- a/src/gui/image/qiconengineplugin.h
+++ b/src/gui/image/qiconengineplugin.h
@@ -55,7 +55,7 @@ class Q_GUI_EXPORT QIconEnginePlugin : public QObject
{
Q_OBJECT
public:
- QIconEnginePlugin(QObject *parent = Q_NULLPTR);
+ QIconEnginePlugin(QObject *parent = nullptr);
~QIconEnginePlugin();
virtual QIconEngine *create(const QString &filename = QString()) = 0;
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 349e0dfbe3..1ea4f1340b 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -95,6 +95,16 @@ static inline QStringList systemIconSearchPaths()
return QStringList();
}
+static inline QStringList systemFallbackSearchPaths()
+{
+ if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) {
+ const QVariant themeHint = theme->themeHint(QPlatformTheme::IconFallbackSearchPaths);
+ if (themeHint.isValid())
+ return themeHint.toStringList();
+ }
+ return QStringList();
+}
+
extern QFactoryLoader *qt_iconEngineFactoryLoader(); // qicon.cpp
void QIconLoader::ensureInitialized()
@@ -158,6 +168,20 @@ QStringList QIconLoader::themeSearchPaths() const
return m_iconDirs;
}
+void QIconLoader::setFallbackSearchPaths(const QStringList &searchPaths)
+{
+ m_fallbackDirs = searchPaths;
+ invalidateKey();
+}
+
+QStringList QIconLoader::fallbackSearchPaths() const
+{
+ if (m_fallbackDirs.isEmpty()) {
+ m_fallbackDirs = systemFallbackSearchPaths();
+ }
+ return m_fallbackDirs;
+}
+
/*!
\internal
Helper class that reads and looks up into the icon-theme.cache generated with
@@ -481,11 +505,54 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
return info;
}
+QThemeIconInfo QIconLoader::lookupFallbackIcon(const QString &iconName) const
+{
+ QThemeIconInfo info;
+
+ const QString pngIconName = iconName + QLatin1String(".png");
+ const QString xpmIconName = iconName + QLatin1String(".xpm");
+ const QString svgIconName = iconName + QLatin1String(".svg");
+
+ const auto searchPaths = QIcon::fallbackSearchPaths();
+ for (const QString &iconDir: searchPaths) {
+ QDir currentDir(iconDir);
+ if (currentDir.exists(pngIconName)) {
+ PixmapEntry *iconEntry = new 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->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->dir.type = QIconDirInfo::Fallback;
+ iconEntry->filename = currentDir.filePath(svgIconName);
+ info.entries.append(iconEntry);
+ break;
+ }
+ }
+
+ if (!info.entries.isEmpty())
+ info.iconName = iconName;
+
+ return info;
+}
+
QThemeIconInfo QIconLoader::loadIcon(const QString &name) const
{
if (!themeName().isEmpty()) {
QStringList visited;
- return findIconHelper(themeName(), name, visited);
+ const QThemeIconInfo iconInfo = findIconHelper(themeName(), name, visited);
+ if (!iconInfo.entries.isEmpty())
+ return iconInfo;
+
+ return lookupFallbackIcon(name);
}
return QThemeIconInfo();
@@ -573,6 +640,8 @@ static bool directoryMatchesSize(const QIconDirInfo &dir, int iconsize, int icon
} else if (dir.type == QIconDirInfo::Threshold) {
return iconsize >= dir.size - dir.threshold &&
iconsize <= dir.size + dir.threshold;
+ } else if (dir.type == QIconDirInfo::Fallback) {
+ return true;
}
Q_ASSERT(1); // Not a valid value
@@ -603,24 +672,26 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon
else if (scaledIconSize > (dir.size + dir.threshold) * dir.scale)
return scaledIconSize - dir.maxSize * dir.scale;
else return 0;
+ } else if (dir.type == QIconDirInfo::Fallback) {
+ return 0;
}
Q_ASSERT(1); // Not a valid value
return INT_MAX;
}
-QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int scale)
+QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &info, const QSize &size, int scale)
{
int iconsize = qMin(size.width(), size.height());
// Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = m_info.entries.size();
+ const int numEntries = info.entries.size();
// Search for exact matches first
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize, scale)) {
return entry;
}
@@ -630,7 +701,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int s
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize, scale);
if (distance < minimalSize) {
minimalSize = distance;
@@ -654,12 +725,14 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
- if (dir.type == QIconDirInfo::Scalable)
+ if (dir.type == QIconDirInfo::Scalable) {
return size;
- else {
+ } 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()));
return QSize(result, result);
}
@@ -718,7 +791,7 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
{
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry)
return entry->pixmap(size, mode, state);
@@ -745,8 +818,13 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
// Gets all sizes from the DirectoryInfo entries
for (int i = 0; i < N; ++i) {
- int size = m_info.entries.at(i)->dir.size;
- sizes.append(QSize(size, size));
+ const QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ if (entry->dir.type == QIconDirInfo::Fallback) {
+ sizes.append(QIcon(entry->filename).availableSizes());
+ } else {
+ int size = entry->dir.size;
+ sizes.append(QSize(size, size));
+ }
}
arg.sizes.swap(sizes); // commit
}
@@ -767,7 +845,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast<QIconEngine::ScaledPixmapArgument*>(data);
// QIcon::pixmap() multiplies size by the device pixel ratio.
const int integerScale = qCeil(arg.scale);
- QIconLoaderEngineEntry *entry = entryForSize(arg.size / integerScale, integerScale);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, arg.size / integerScale, integerScale);
arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap();
}
break;
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 5f3a3ef948..746e871fb1 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -69,7 +69,7 @@ class QIconLoader;
struct QIconDirInfo
{
- enum Type { Fixed, Scalable, Threshold };
+ enum Type { Fixed, Scalable, Threshold, Fallback };
QIconDirInfo(const QString &_path = QString()) :
path(_path),
size(0),
@@ -101,13 +101,13 @@ public:
struct ScalableEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QIcon svgIcon;
};
struct PixmapEntry : public QIconLoaderEngineEntry
{
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
+ QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
QPixmap basePixmap;
};
@@ -125,19 +125,20 @@ public:
QIconLoaderEngine(const QString& iconName = QString());
~QIconLoaderEngine();
- void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE;
- QIconEngine *clone() const Q_DECL_OVERRIDE;
- bool read(QDataStream &in) Q_DECL_OVERRIDE;
- bool write(QDataStream &out) const Q_DECL_OVERRIDE;
+ void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+ 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;
+
+ Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
private:
- QString key() const Q_DECL_OVERRIDE;
+ QString key() const override;
bool hasIcon() const;
void ensureLoaded();
- void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- QIconLoaderEngineEntry *entryForSize(const QSize &size, int scale = 1);
+ void virtual_hook(int id, void *data) override;
QIconLoaderEngine(const QIconLoaderEngine &other);
QThemeIconInfo m_info;
@@ -179,6 +180,8 @@ public:
QIconTheme theme() { return themeList.value(themeName()); }
void setThemeSearchPath(const QStringList &searchPaths);
QStringList themeSearchPaths() const;
+ void setFallbackSearchPaths(const QStringList &searchPaths);
+ QStringList fallbackSearchPaths() const;
QIconDirInfo dirInfo(int dirindex);
static QIconLoader *instance();
void updateSystemTheme();
@@ -190,6 +193,8 @@ private:
QThemeIconInfo findIconHelper(const QString &themeName,
const QString &iconName,
QStringList &visited) const;
+ QThemeIconInfo lookupFallbackIcon(const QString &iconName) const;
+
uint m_themeKey;
bool m_supportsSvg;
bool m_initialized;
@@ -198,6 +203,7 @@ private:
mutable QString m_systemTheme;
mutable QStringList m_iconDirs;
mutable QHash <QString, QIconTheme> themeList;
+ mutable QStringList m_fallbackDirs;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index bd10012bf6..7fcae12cbd 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -127,11 +127,11 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
// sanity check for potential overflows
- if (INT_MAX/depth < width
+ if (std::numeric_limits<int>::max()/depth < width
|| bytes_per_line <= 0
|| height <= 0
- || INT_MAX/uint(bytes_per_line) < height
- || INT_MAX/sizeof(uchar *) < uint(height))
+ || std::numeric_limits<qsizetype>::max()/uint(bytes_per_line) < height
+ || std::numeric_limits<int>::max()/sizeof(uchar *) < uint(height))
return 0;
QScopedPointer<QImageData> d(new QImageData);
@@ -452,7 +452,7 @@ bool QImageData::checkForAlphaPixels() const
used. For more information see the
\l {QImage#Image Formats}{Image Formats} section.
- The format(), bytesPerLine(), and byteCount() functions provide
+ The format(), bytesPerLine(), and sizeInBytes() functions provide
low-level information about the data stored in the image.
The cacheKey() function returns a number that uniquely
@@ -1449,26 +1449,43 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
/*!
\since 4.6
+ \obsolete
Returns the number of bytes occupied by the image data.
- \sa bytesPerLine(), bits(), {QImage#Image Information}{Image
+ Note this method should never be called on an image larger than 2 gigabytes.
+ Instead use sizeInBytes().
+
+ \sa sizeInBytes(), bytesPerLine(), bits(), {QImage#Image Information}{Image
Information}
*/
int QImage::byteCount() const
{
+ Q_ASSERT(!d || d->nbytes < std::numeric_limits<int>::max());
+ return d ? int(d->nbytes) : 0;
+}
+
+/*!
+ \since 5.10
+ Returns the image data size in bytes.
+
+ \sa byteCount(), bytesPerLine(), bits(), {QImage#Image Information}{Image
+ Information}
+*/
+qsizetype QImage::sizeInBytes() const
+{
return d ? d->nbytes : 0;
}
/*!
Returns the number of bytes per image scanline.
- This is equivalent to byteCount() / height().
+ This is equivalent to sizeInBytes() / height() if height() is non-zero.
\sa scanLine()
*/
int QImage::bytesPerLine() const
{
- return (d && d->height) ? d->nbytes / d->height : 0;
+ return d ? d->bytes_per_line : 0;
}
@@ -1595,7 +1612,7 @@ const uchar *QImage::constScanLine(int i) const
data, thus ensuring that this QImage is the only one using the
current return value.
- \sa scanLine(), byteCount(), constBits()
+ \sa scanLine(), sizeInBytes(), constBits()
*/
uchar *QImage::bits()
{
@@ -1959,7 +1976,8 @@ QImage::Format QImage::format() const
}
/*!
- \fn QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) const
+ \fn QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) const &
+ \fn QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) &&
Returns a copy of the image in the given \a format.
@@ -2117,8 +2135,8 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q
/*!
\since 5.9
- Changes the \a format of the image without changing the data. Only
- works between formats of the same depth.
+ Changes the format of the image to \a format without changing the
+ data. Only works between formats of the same depth.
Returns \c true if successful.
@@ -2971,7 +2989,9 @@ QImage QImage::createMaskFromColor(QRgb color, Qt::MaskMode mode) const
}
/*!
- \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const
+ \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) const &
+ \fn QImage QImage::mirrored(bool horizontal = false, bool vertical = true) &&
+
Returns a mirror of the image, mirrored in the horizontal and/or
the vertical direction depending on whether \a horizontal and \a
vertical are set to true or false.
@@ -3176,7 +3196,9 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical)
}
/*!
- \fn QImage QImage::rgbSwapped() const
+ \fn QImage QImage::rgbSwapped() const &
+ \fn QImage QImage::rgbSwapped() &&
+
Returns a QImage in which the values of the red and blue
components of all pixels have been swapped, effectively converting
an RGB image to an BGR image.
@@ -3245,14 +3267,31 @@ QImage QImage::rgbSwapped_helper() const
res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
}
break;
- case Format_RGB32:
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
case Format_RGBX8888:
case Format_RGBA8888:
case Format_RGBA8888_Premultiplied:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ res = QImage(d->width, d->height, d->format);
+ QIMAGE_SANITYCHECK_MEMORY(res);
+ for (int i = 0; i < d->height; i++) {
+ uint *q = (uint*)res.scanLine(i);
+ const uint *p = (const uint*)constScanLine(i);
+ const uint *end = p + d->width;
+ while (p < end) {
+ uint c = *p;
+ *q = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
+ p++;
+ q++;
+ }
+ }
+ break;
+#else
+ // On little-endian rgba8888 is abgr32 and can use same rgb-swap as argb32
+ Q_FALLTHROUGH();
#endif
+ case Format_RGB32:
+ case Format_ARGB32:
+ case Format_ARGB32_Premultiplied:
res = QImage(d->width, d->height, d->format);
QIMAGE_SANITYCHECK_MEMORY(res);
for (int i = 0; i < d->height; i++) {
@@ -3336,14 +3375,27 @@ void QImage::rgbSwapped_inplace()
d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00));
}
break;
- case Format_RGB32:
- case Format_ARGB32:
- case Format_ARGB32_Premultiplied:
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
case Format_RGBX8888:
case Format_RGBA8888:
case Format_RGBA8888_Premultiplied:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ for (int i = 0; i < d->height; i++) {
+ uint *p = (uint*)scanLine(i);
+ uint *end = p + d->width;
+ while (p < end) {
+ uint c = *p;
+ *p = ((c << 16) & 0xff000000) | ((c >> 16) & 0xff00) | (c & 0x00ff00ff);
+ p++;
+ }
+ }
+ break;
+#else
+ // On little-endian rgba8888 is abgr32 and can use same rgb-swap as argb32
+ Q_FALLTHROUGH();
#endif
+ case Format_RGB32:
+ case Format_ARGB32:
+ case Format_ARGB32_Premultiplied:
for (int i = 0; i < d->height; i++) {
uint *p = (uint*)scanLine(i);
uint *end = p + d->width;
@@ -4662,12 +4714,12 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
if (dImage.d->colortable.size() < 256) {
// colors are left in the color table, so pick that one as transparent
dImage.d->colortable.append(0x0);
- memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount());
+ memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
} else {
- memset(dImage.bits(), 0, dImage.byteCount());
+ memset(dImage.bits(), 0, dImage.d->nbytes);
}
} else
- memset(dImage.bits(), 0x00, dImage.byteCount());
+ memset(dImage.bits(), 0x00, dImage.d->nbytes);
if (target_format >= QImage::Format_RGB32) {
// Prevent QPainter from applying devicePixelRatio corrections
@@ -4762,8 +4814,8 @@ bool QImageData::convertInPlace(QImage::Format newFormat, Qt::ImageConversionFla
QDebug operator<<(QDebug dbg, const QImage &i)
{
QDebugStateSaver saver(dbg);
- dbg.resetFormat();
dbg.nospace();
+ dbg.noquote();
dbg << "QImage(";
if (i.isNull()) {
dbg << "null";
@@ -4771,8 +4823,15 @@ QDebug operator<<(QDebug dbg, const QImage &i)
dbg << i.size() << ",format=" << i.format() << ",depth=" << i.depth();
if (i.colorCount())
dbg << ",colorCount=" << i.colorCount();
+ const int bytesPerLine = i.bytesPerLine();
dbg << ",devicePixelRatio=" << i.devicePixelRatio()
- << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount();
+ << ",bytesPerLine=" << bytesPerLine << ",sizeInBytes=" << i.sizeInBytes();
+ if (dbg.verbosity() > 2 && i.height() > 0) {
+ const int outputLength = qMin(bytesPerLine, 24);
+ dbg << ",line0="
+ << QByteArray(reinterpret_cast<const char *>(i.scanLine(0)), outputLength).toHex()
+ << "...";
+ }
}
dbg << ')';
return dbg;
@@ -4794,7 +4853,7 @@ QDebug operator<<(QDebug dbg, const QImage &i)
Returns the number of bytes occupied by the image data.
- \sa byteCount()
+ \sa sizeInBytes()
*/
/*!
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 225ef3d2e8..9b76b62f24 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -136,20 +136,20 @@ public:
QImage() Q_DECL_NOEXCEPT;
QImage(const QSize &size, Format format);
QImage(int width, int height, Format format);
- QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR);
- QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR);
- QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR);
- QImage(const uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = Q_NULLPTR, void *cleanupInfo = Q_NULLPTR);
+ QImage(uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
+ QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
+ QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
+ QImage(const uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr);
#ifndef QT_NO_IMAGEFORMAT_XPM
explicit QImage(const char * const xpm[]);
#endif
- explicit QImage(const QString &fileName, const char *format = Q_NULLPTR);
+ explicit QImage(const QString &fileName, const char *format = nullptr);
QImage(const QImage &);
#ifdef Q_COMPILER_RVALUE_REFS
inline QImage(QImage &&other) Q_DECL_NOEXCEPT
- : QPaintDevice(), d(Q_NULLPTR)
+ : QPaintDevice(), d(nullptr)
{ qSwap(d, other.d); }
#endif
~QImage();
@@ -164,7 +164,7 @@ public:
bool isNull() const;
- int devType() const Q_DECL_OVERRIDE;
+ int devType() const override;
bool operator==(const QImage &) const;
bool operator!=(const QImage &) const;
@@ -214,7 +214,10 @@ public:
const uchar *bits() const;
const uchar *constBits() const;
- int byteCount() const;
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED_X("Use sizeInBytes") int byteCount() const;
+#endif
+ qsizetype sizeInBytes() const;
uchar *scanLine(int);
const uchar *scanLine(int) const;
@@ -291,16 +294,16 @@ public:
bool load(QIODevice *device, const char* format);
- bool load(const QString &fileName, const char *format = Q_NULLPTR);
- bool loadFromData(const uchar *buf, int len, const char *format = Q_NULLPTR);
- inline bool loadFromData(const QByteArray &data, const char *aformat = Q_NULLPTR)
+ bool load(const QString &fileName, const char *format = nullptr);
+ bool loadFromData(const uchar *buf, int len, const char *format = nullptr);
+ inline bool loadFromData(const QByteArray &data, const char *aformat = nullptr)
{ return loadFromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), aformat); }
- bool save(const QString &fileName, const char *format = Q_NULLPTR, int quality = -1) const;
- bool save(QIODevice *device, const char *format = Q_NULLPTR, int quality = -1) const;
+ 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 = Q_NULLPTR);
- inline static QImage fromData(const QByteArray &data, const char *format = Q_NULLPTR)
+ static QImage fromData(const uchar *data, int size, const char *format = nullptr);
+ inline static QImage fromData(const QByteArray &data, const char *format = nullptr)
{ return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); }
#if QT_DEPRECATED_SINCE(5, 0)
@@ -308,7 +311,7 @@ public:
#endif
qint64 cacheKey() const;
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const override;
// Auxiliary data
int dotsPerMeterX() const;
@@ -332,7 +335,7 @@ public:
#endif
#if QT_DEPRECATED_SINCE(5, 0)
- QT_DEPRECATED inline QString text(const char *key, const char *lang = Q_NULLPTR) const;
+ QT_DEPRECATED inline QString text(const char *key, const char *lang = nullptr) const;
QT_DEPRECATED inline QList<QImageTextKeyLang> textList() const;
QT_DEPRECATED inline QStringList textLanguages() const;
QT_DEPRECATED inline QString text(const QImageTextKeyLang&) const;
@@ -346,7 +349,7 @@ public:
#endif
protected:
- virtual int metric(PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ virtual int metric(PaintDeviceMetric metric) const override;
QImage mirrored_helper(bool horizontal, bool vertical) const;
QImage rgbSwapped_helper() const;
void mirrored_inplace(bool horizontal, bool vertical);
@@ -468,7 +471,7 @@ inline void QImage::setNumColors(int n)
inline int QImage::numBytes() const
{
- return byteCount();
+ return int(sizeInBytes());
}
#endif
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 50fad1566c..4eef617336 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -40,6 +40,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
#include <private/qcolorprofile_p.h>
+#include <private/qendian_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
#include <qendian.h>
@@ -126,8 +127,8 @@ static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint
return buffer;
}
-static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
buffer[i] = 0xff000000 |src[i];
@@ -160,8 +161,9 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
// If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
convertFromARGB32PM = destLayout->convertFromRGB32;
} else {
+ // The drawhelpers do not mask the alpha value in RGB32, we want to here.
if (src->format == QImage::Format_RGB32)
- convertToARGB32PM = convertRGB32ToARGB32PM;
+ convertToARGB32PM = maskRGB32;
if (dest->format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
@@ -171,6 +173,15 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
+ if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) &&
+ destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
+ convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM;
+ if (dest->format == QImage::Format_RGB32)
+ convertFromARGB32PM = maskRGB32;
+ else
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ }
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
@@ -221,7 +232,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
convertFromARGB32PM = destLayout->convertFromRGB32;
} else {
if (data->format == QImage::Format_RGB32)
- convertToARGB32PM = convertRGB32ToARGB32PM;
+ convertToARGB32PM = maskRGB32;
if (dst_format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
@@ -231,6 +242,15 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
+ if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) &&
+ destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
+ convertToARGB32PM = qPixelLayouts[data->format + 1].convertToARGB32PM;
+ if (dst_format == QImage::Format_RGB32)
+ convertFromARGB32PM = maskRGB32;
+ else
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ }
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
@@ -322,10 +342,10 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dest_data, con
// Handle 4 pixels at a time 12 bytes input to 16 bytes output.
for (; pixel + 3 < len; pixel += 4) {
- const quint32 *src_packed = (const quint32 *) src_data;
- const quint32 src1 = qFromBigEndian(src_packed[0]);
- const quint32 src2 = qFromBigEndian(src_packed[1]);
- const quint32 src3 = qFromBigEndian(src_packed[2]);
+ const quint32_be *src_packed = reinterpret_cast<const quint32_be *>(src_data);
+ const quint32 src1 = src_packed[0];
+ const quint32 src2 = src_packed[1];
+ const quint32 src3 = src_packed[2];
dest_data[0] = 0xff000000 | (src1 >> 8);
dest_data[1] = 0xff000000 | (src1 << 16) | (src2 >> 16);
@@ -803,8 +823,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve
const int depth = 32;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qsizetype dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qsizetype nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -857,8 +877,8 @@ static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversi
const int depth = 32;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qsizetype dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qsizetype nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -925,8 +945,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers
const int depth = 16;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qsizetype dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qsizetype nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -982,8 +1002,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl
const int depth = 16;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int src_bytes_per_line = data->bytes_per_line;
+ const qsizetype dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qsizetype src_bytes_per_line = data->bytes_per_line;
quint32 *src_data = (quint32 *) data->data;
quint16 *dst_data = (quint16 *) data->data;
@@ -1237,9 +1257,9 @@ void dither_to_Mono(QImageData *dst, const QImageData *src,
}
uchar *dst_data = dst->data;
- int dst_bpl = dst->bytes_per_line;
+ qsizetype dst_bpl = dst->bytes_per_line;
const uchar *src_data = src->data;
- int src_bpl = src->bytes_per_line;
+ qsizetype src_bpl = src->bytes_per_line;
switch (dithermode) {
case Diffuse: {
@@ -1892,8 +1912,8 @@ static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src,
if (simpleCase)
memcpy(dest->data, src->data, src->bytes_per_line * src->height);
else {
- int size = src->bytes_per_line * src->height;
- for (int i = 0; i < size; ++i) {
+ qsizetype size = src->bytes_per_line * src->height;
+ for (qsizetype i = 0; i < size; ++i) {
dest->data[i] = translate[src->data[i]];
}
}
@@ -1916,8 +1936,8 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s
if (simpleCase)
memcpy(dest->data, src->data, src->bytes_per_line * src->height);
else {
- int size = src->bytes_per_line * src->height;
- for (int i = 0; i < size; ++i) {
+ qsizetype size = src->bytes_per_line * src->height;
+ for (qsizetype i = 0; i < size; ++i) {
dest->data[i] = translate[src->data[i]];
}
}
diff --git a/src/gui/image/qimage_darwin.mm b/src/gui/image/qimage_darwin.mm
index 3764bef06b..a5c391ad21 100644
--- a/src/gui/image/qimage_darwin.mm
+++ b/src/gui/image/qimage_darwin.mm
@@ -130,7 +130,7 @@ CGImageRef QImage::toCGImage() const
auto deleter = [](void *image, const void *, size_t)
{ delete static_cast<QImage *>(image); };
QCFType<CGDataProviderRef> dataProvider =
- CGDataProviderCreateWithData(new QImage(*this), bits(), byteCount(), deleter);
+ CGDataProviderCreateWithData(new QImage(*this), bits(), sizeInBytes(), deleter);
QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 775ab6d541..befecbfe8b 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -71,12 +71,12 @@ struct Q_GUI_EXPORT QImageData { // internal image data
int width;
int height;
int depth;
- int nbytes; // number of bytes data
+ qsizetype nbytes; // number of bytes data
qreal devicePixelRatio;
QVector<QRgb> colortable;
uchar *data;
QImage::Format format;
- int bytes_per_line;
+ qsizetype bytes_per_line;
int ser_no; // serial number
int detach_no;
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index baf9853259..35984dd6a5 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -140,7 +140,7 @@ class Q_GUI_EXPORT QImageIOPlugin : public QObject
{
Q_OBJECT
public:
- explicit QImageIOPlugin(QObject *parent = Q_NULLPTR);
+ explicit QImageIOPlugin(QObject *parent = nullptr);
virtual ~QImageIOPlugin();
enum Capability {
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index e1089936c2..7086e102ea 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -570,6 +570,16 @@ bool QImageReaderPrivate::initHandler()
// probe the file extension
if (deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly) && autoDetectImageFormat) {
+ Q_ASSERT(qobject_cast<QFile*>(device) != 0); // future-proofing; for now this should always be the case, so...
+ QFile *file = static_cast<QFile *>(device);
+
+ if (file->error() == QFileDevice::ResourceError) {
+ // this is bad. we should abort the open attempt and note the failure.
+ imageReaderError = QImageReader::DeviceError;
+ errorString = file->errorString();
+ return false;
+ }
+
QList<QByteArray> extensions = QImageReader::supportedImageFormats();
if (!format.isEmpty()) {
// Try the most probable extension first
@@ -580,7 +590,6 @@ bool QImageReaderPrivate::initHandler()
int currentExtension = 0;
- QFile *file = static_cast<QFile *>(device);
QString fileName = file->fileName();
do {
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index ab15d8ee29..a39d204677 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -87,6 +87,9 @@
\value UnsupportedFormatError Qt does not support the requested
image format.
+ \value InvalidImageError An attempt was made to write an invalid QImage. An
+ example of an invalid image would be a null QImage.
+
\value UnknownError An unknown error occurred. If you get this
value after calling write(), it is most likely caused by a bug in
QImageWriter.
@@ -736,6 +739,13 @@ extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orie
*/
bool QImageWriter::write(const QImage &image)
{
+ // Do this before canWrite, so it doesn't create a file if this fails.
+ if (Q_UNLIKELY(image.isNull())) {
+ d->imageWriterError = QImageWriter::InvalidImageError;
+ d->errorString = QImageWriter::tr("Image is empty");
+ return false;
+ }
+
if (!canWrite())
return false;
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 58f8c51472..fd1fdd07e8 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -60,7 +60,8 @@ public:
enum ImageWriterError {
UnknownError,
DeviceError,
- UnsupportedFormatError
+ UnsupportedFormatError,
+ InvalidImageError
};
QImageWriter();
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index fbbf6e9802..d5e8b1b974 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -161,6 +161,8 @@
This signal is emitted by QMovie when the error \a error occurred during
playback. QMovie will stop the movie, and enter QMovie::NotRunning state.
+
+ \sa lastError(), lastErrorString()
*/
/*! \fn void QMovie::finished()
@@ -328,6 +330,8 @@ int QMoviePrivate::speedAdjustedDelay(int delay) const
*/
QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
{
+ Q_Q(QMovie);
+
if (frameNumber < 0)
return QFrameInfo(); // Invalid
@@ -356,7 +360,8 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
reader = new QImageReader(device, format);
else
reader = new QImageReader(absoluteFilePath, format);
- (void)reader->canRead(); // Provoke a device->open() call
+ if (!reader->canRead()) // Provoke a device->open() call
+ emit q->error(reader->error());
reader->device()->seek(initialDevicePos);
reader->setBackgroundColor(bgColor);
reader->setScaledSize(scaledSize);
@@ -523,8 +528,20 @@ void QMoviePrivate::_q_loadNextFrame(bool starting)
*/
bool QMoviePrivate::isValid() const
{
- return (greatestFrameNumber >= 0) // have we seen valid data
- || reader->canRead(); // or does the reader see valid data
+ Q_Q(const QMovie);
+
+ if (greatestFrameNumber >= 0)
+ return true; // have we seen valid data
+ bool canRead = reader->canRead();
+ if (!canRead) {
+ // let the consumer know it's broken
+ //
+ // ### the const_cast here is ugly, but 'const' of this method is
+ // technically wrong right now, since it may cause the underlying device
+ // to open.
+ emit const_cast<QMovie*>(q)->error(reader->error());
+ }
+ return canRead;
}
/*!
@@ -775,6 +792,8 @@ QImage QMovie::currentImage() const
/*!
Returns \c true if the movie is valid (e.g., the image data is readable and
the image format is supported); otherwise returns \c false.
+
+ For information about why the movie is not valid, see lastError().
*/
bool QMovie::isValid() const
{
@@ -783,6 +802,29 @@ bool QMovie::isValid() const
}
/*!
+ Returns the most recent error that occurred while attempting to read image data.
+
+ \sa lastErrorString()
+*/
+QImageReader::ImageReaderError QMovie::lastError() const
+{
+ Q_D(const QMovie);
+ return d->reader->error();
+}
+
+/*!
+ Returns a human-readable representation of the most recent error that occurred
+ while attempting to read image data.
+
+ \sa lastError()
+*/
+QString QMovie::lastErrorString() const
+{
+ Q_D(const QMovie);
+ return d->reader->errorString();
+}
+
+/*!
Returns the number of frames in the movie.
Certain animation formats do not support this feature, in which
diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h
index 930d502892..e13c528894 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -79,9 +79,9 @@ public:
};
Q_ENUM(CacheMode)
- explicit QMovie(QObject *parent = Q_NULLPTR);
- explicit QMovie(QIODevice *device, const QByteArray &format = QByteArray(), QObject *parent = Q_NULLPTR);
- explicit QMovie(const QString &fileName, const QByteArray &format = QByteArray(), QObject *parent = Q_NULLPTR);
+ explicit QMovie(QObject *parent = nullptr);
+ explicit QMovie(QIODevice *device, const QByteArray &format = QByteArray(), QObject *parent = nullptr);
+ explicit QMovie(const QString &fileName, const QByteArray &format = QByteArray(), QObject *parent = nullptr);
~QMovie();
static QList<QByteArray> supportedFormats();
@@ -105,6 +105,8 @@ public:
QPixmap currentPixmap() const;
bool isValid() const;
+ QImageReader::ImageReaderError lastError() const;
+ QString lastErrorString() const;
bool jumpToFrame(int frameNumber);
int loopCount() const;
diff --git a/src/gui/image/qpaintengine_pic_p.h b/src/gui/image/qpaintengine_pic_p.h
index 7c690c1498..c3044796ad 100644
--- a/src/gui/image/qpaintengine_pic_p.h
+++ b/src/gui/image/qpaintengine_pic_p.h
@@ -68,10 +68,10 @@ public:
QPicturePaintEngine();
~QPicturePaintEngine();
- bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
- bool end() Q_DECL_OVERRIDE;
+ bool begin(QPaintDevice *pdev) override;
+ bool end() override;
- void updateState(const QPaintEngineState &state) Q_DECL_OVERRIDE;
+ void updateState(const QPaintEngineState &state) override;
void updatePen(const QPen &pen);
void updateBrush(const QBrush &brush);
@@ -86,18 +86,18 @@ public:
void updateClipEnabled(bool enabled);
void updateOpacity(qreal opacity);
- void drawEllipse(const QRectF &rect) Q_DECL_OVERRIDE;
- void drawPath(const QPainterPath &path) Q_DECL_OVERRIDE;
- void drawPolygon(const QPointF *points, int numPoints, PolygonDrawMode mode) Q_DECL_OVERRIDE;
+ void drawEllipse(const QRectF &rect) override;
+ void drawPath(const QPainterPath &path) override;
+ void drawPolygon(const QPointF *points, int numPoints, PolygonDrawMode mode) override;
using QPaintEngine::drawPolygon;
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
- void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) Q_DECL_OVERRIDE;
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
+ void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override;
void drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
- Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
- void drawTextItem(const QPointF &p, const QTextItem &ti) Q_DECL_OVERRIDE;
+ Qt::ImageConversionFlags flags = Qt::AutoColor) override;
+ void drawTextItem(const QPointF &p, const QTextItem &ti) override;
- Type type() const Q_DECL_OVERRIDE { return Picture; }
+ Type type() const override { return Picture; }
protected:
QPicturePaintEngine(QPaintEnginePrivate &dptr);
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 010f5ecf67..7aa221948e 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -456,8 +456,8 @@ public:
QFakeDevice() { dpi_x = qt_defaultDpiX(); dpi_y = qt_defaultDpiY(); }
void setDpiX(int dpi) { dpi_x = dpi; }
void setDpiY(int dpi) { dpi_y = dpi; }
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE { return 0; }
- int metric(PaintDeviceMetric m) const Q_DECL_OVERRIDE
+ QPaintEngine *paintEngine() const override { return 0; }
+ int metric(PaintDeviceMetric m) const override
{
switch(m) {
case PdmPhysicalDpiX:
@@ -1194,6 +1194,7 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qpictureformatplugin.h"
QT_END_INCLUDE_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
\obsolete
@@ -1284,6 +1285,7 @@ QList<QByteArray> QPicture::outputFormats()
{
return QPictureIO::outputFormats();
}
+#endif // QT_DEPRECATED_SINCE(5, 10)
/*****************************************************************************
QPictureIO member functions
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 8da11caee4..ec7b4bd7e3 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -62,17 +62,17 @@ public:
bool isNull() const;
- int devType() const Q_DECL_OVERRIDE;
+ int devType() const override;
uint size() const;
const char* data() const;
virtual void setData(const char* data, uint size);
bool play(QPainter *p);
- bool load(QIODevice *dev, const char *format = Q_NULLPTR);
- bool load(const QString &fileName, const char *format = Q_NULLPTR);
- bool save(QIODevice *dev, const char *format = Q_NULLPTR);
- bool save(const QString &fileName, const char *format = Q_NULLPTR);
+ bool load(QIODevice *dev, const char *format = nullptr);
+ bool load(const QString &fileName, const char *format = nullptr);
+ bool save(QIODevice *dev, const char *format = nullptr);
+ bool save(const QString &fileName, const char *format = nullptr);
QRect boundingRect() const;
void setBoundingRect(const QRect &r);
@@ -90,18 +90,20 @@ public:
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QPicture &p);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QPicture &p);
- static const char* pictureFormat(const QString &fileName);
- static QList<QByteArray> inputFormats();
- static QList<QByteArray> outputFormats();
- static QStringList inputFormatList();
- static QStringList outputFormatList();
+#if QT_DEPRECATED_SINCE(5, 10)
+ static QT_DEPRECATED const char* pictureFormat(const QString &fileName);
+ static QT_DEPRECATED QList<QByteArray> inputFormats();
+ static QT_DEPRECATED QList<QByteArray> outputFormats();
+ static QT_DEPRECATED QStringList inputFormatList();
+ static QT_DEPRECATED QStringList outputFormatList();
+#endif // QT_DEPRECATED_SINCE(5, 10)
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const override;
protected:
QPicture(QPicturePrivate &data);
- int metric(PaintDeviceMetric m) const Q_DECL_OVERRIDE;
+ int metric(PaintDeviceMetric m) const override;
private:
bool exec(QPainter *p, QDataStream &ds, int i);
diff --git a/src/gui/image/qpictureformatplugin.h b/src/gui/image/qpictureformatplugin.h
index 32195687c7..3f59c04d79 100644
--- a/src/gui/image/qpictureformatplugin.h
+++ b/src/gui/image/qpictureformatplugin.h
@@ -60,7 +60,7 @@ class Q_GUI_EXPORT QPictureFormatPlugin : public QObject
{
Q_OBJECT
public:
- explicit QPictureFormatPlugin(QObject *parent = Q_NULLPTR);
+ explicit QPictureFormatPlugin(QObject *parent = nullptr);
~QPictureFormatPlugin();
virtual bool loadPicture(const QString &format, const QString &filename, QPicture *pic);
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 0aa05a04e2..5b3e3985a7 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -596,44 +596,7 @@ void QPixmap::setMask(const QBitmap &mask)
return;
detach();
-
- QImage image = data->toImage();
- if (mask.size().isEmpty()) {
- if (image.depth() != 1) { // hw: ????
- image = image.convertToFormat(QImage::Format_RGB32);
- }
- } else {
- const int w = image.width();
- const int h = image.height();
-
- switch (image.depth()) {
- case 1: {
- const QImage imageMask = mask.toImage().convertToFormat(image.format());
- for (int y = 0; y < h; ++y) {
- const uchar *mscan = imageMask.scanLine(y);
- uchar *tscan = image.scanLine(y);
- int bytesPerLine = image.bytesPerLine();
- for (int i = 0; i < bytesPerLine; ++i)
- tscan[i] &= mscan[i];
- }
- break;
- }
- default: {
- const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
- image = 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);
- for (int x = 0; x < w; ++x) {
- if (!(mscan[x>>3] & (1 << (x&7))))
- tscan[x] = 0;
- }
- }
- break;
- }
- }
- }
- data->fromImage(image, Qt::AutoColor);
+ data->setMask(mask);
}
/*!
@@ -1496,37 +1459,7 @@ QPaintEngine *QPixmap::paintEngine() const
*/
QBitmap QPixmap::mask() const
{
- if (!data || !hasAlphaChannel())
- return QBitmap();
-
- const 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 int w = image.width();
- const int h = image.height();
-
- QImage mask(w, h, QImage::Format_MonoLSB);
- if (mask.isNull()) // allocation failed
- return QBitmap();
-
- mask.setColorCount(2);
- mask.setColor(0, QColor(Qt::color0).rgba());
- mask.setColor(1, QColor(Qt::color1).rgba());
-
- const int bpl = mask.bytesPerLine();
-
- for (int y = 0; y < h; ++y) {
- const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
- uchar *dest = mask.scanLine(y);
- memset(dest, 0, bpl);
- for (int x = 0; x < w; ++x) {
- if (qAlpha(*src) > 0)
- dest[x >> 3] |= (1 << (x & 7));
- ++src;
- }
- }
-
- return QBitmap::fromImage(mask);
+ return data ? data->mask() : QBitmap();
}
/*!
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index d651b57fd5..55cca7a766 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -65,7 +65,7 @@ public:
explicit QPixmap(QPlatformPixmap *data);
QPixmap(int w, int h);
explicit QPixmap(const QSize &);
- QPixmap(const QString& fileName, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ QPixmap(const QString& fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
#ifndef QT_NO_IMAGEFORMAT_XPM
explicit QPixmap(const char * const xpm[]);
#endif
@@ -83,7 +83,7 @@ public:
operator QVariant() const;
bool isNull() const;
- int devType() const Q_DECL_OVERRIDE;
+ int devType() const override;
int width() const;
int height() const;
@@ -138,19 +138,19 @@ public:
}
#endif
- bool load(const QString& fileName, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
- bool loadFromData(const uchar *buf, uint len, const char* format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
- inline bool loadFromData(const QByteArray &data, const char* format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor);
- bool save(const QString& fileName, const char* format = Q_NULLPTR, int quality = -1) const;
- bool save(QIODevice* device, const char* format = Q_NULLPTR, int quality = -1) const;
+ bool load(const QString& fileName, const char *format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ bool loadFromData(const uchar *buf, uint len, const char* format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ inline bool loadFromData(const QByteArray &data, const char* format = nullptr, Qt::ImageConversionFlags flags = Qt::AutoColor);
+ 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;
bool convertFromImage(const QImage &img, Qt::ImageConversionFlags flags = Qt::AutoColor);
inline QPixmap copy(int x, int y, int width, int height) const;
QPixmap copy(const QRect &rect = QRect()) const;
- inline void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = Q_NULLPTR);
- void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = Q_NULLPTR);
+ inline void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = nullptr);
+ void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = nullptr);
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; }
@@ -162,7 +162,7 @@ public:
bool isQBitmap() const;
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const override;
inline bool operator!() const { return isNull(); }
@@ -172,7 +172,7 @@ public:
#endif
protected:
- int metric(PaintDeviceMetric) const Q_DECL_OVERRIDE;
+ int metric(PaintDeviceMetric) const override;
static QPixmap fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
private:
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 950695a9d7..646e737afa 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -41,6 +41,7 @@
#include <qpainter.h>
#include <qimage.h>
+#include <qrandom.h>
#include <qscreen.h>
#include <private/qguiapplication_p.h>
@@ -190,8 +191,8 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image,
uchar *mem = thisImg->bits();
const uchar *bits = correctFormatPic.constBits();
- int bytesCopied = 0;
- while (bytesCopied < correctFormatPic.byteCount()) {
+ qsizetype bytesCopied = 0;
+ while (bytesCopied < correctFormatPic.sizeInBytes()) {
memcpy(mem,bits,correctFormatPic.bytesPerLine());
mem += thisImg->bytesPerLine();
bits += correctFormatPic.bytesPerLine();
@@ -252,7 +253,7 @@ QImage *QBlittablePlatformPixmap::overlay()
m_rasterOverlay->size() != QSize(w,h)){
m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied);
m_rasterOverlay->fill(0x00000000);
- uint color = (qrand() % 11)+7;
+ uint color = QRandomGenerator::global()->bounded(11)+7;
m_overlayColor = QColor(Qt::GlobalColor(color));
m_overlayColor.setAlpha(0x88);
diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h
index 9889cfb8ec..d70cbcdcc3 100644
--- a/src/gui/image/qpixmap_blitter_p.h
+++ b/src/gui/image/qpixmap_blitter_p.h
@@ -69,17 +69,17 @@ public:
QBlittable *blittable() const;
void setBlittable(QBlittable *blittable);
- void resize(int width, int height) Q_DECL_OVERRIDE;
- int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
- void fill(const QColor &color) Q_DECL_OVERRIDE;
- QImage *buffer() Q_DECL_OVERRIDE;
- QImage toImage() const Q_DECL_OVERRIDE;
- bool hasAlphaChannel() const Q_DECL_OVERRIDE;
- void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
-
- QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ void resize(int width, int height) override;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+ void fill(const QColor &color) override;
+ QImage *buffer() override;
+ QImage toImage() const override;
+ bool hasAlphaChannel() const override;
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags) override;
+ qreal devicePixelRatio() const override;
+ void setDevicePixelRatio(qreal scaleFactor) override;
+
+ QPaintEngine *paintEngine() const override;
void markRasterOverlay(const QRectF &);
void markRasterOverlay(const QPointF &, const QTextItem &);
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index 6ea965a324..cff962181a 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -63,28 +63,28 @@ public:
QRasterPlatformPixmap(PixelType type);
~QRasterPlatformPixmap();
- QPlatformPixmap *createCompatiblePlatformPixmap() const Q_DECL_OVERRIDE;
-
- void resize(int width, int height) Q_DECL_OVERRIDE;
- bool fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
- void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
- void fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
- void fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
-
- void copy(const QPlatformPixmap *data, const QRect &rect) Q_DECL_OVERRIDE;
- bool scroll(int dx, int dy, const QRect &rect) Q_DECL_OVERRIDE;
- void fill(const QColor &color) Q_DECL_OVERRIDE;
- bool hasAlphaChannel() const Q_DECL_OVERRIDE;
- QImage toImage() const Q_DECL_OVERRIDE;
- QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
- QPaintEngine* paintEngine() const Q_DECL_OVERRIDE;
- QImage* buffer() Q_DECL_OVERRIDE;
- qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
+ QPlatformPixmap *createCompatiblePlatformPixmap() const override;
+
+ void resize(int width, int height) override;
+ bool fromData(const uchar *buffer, uint len, const char *format, Qt::ImageConversionFlags flags) override;
+ void fromImage(const QImage &image, Qt::ImageConversionFlags flags) override;
+ void fromImageInPlace(QImage &image, Qt::ImageConversionFlags flags) override;
+ void fromImageReader(QImageReader *imageReader, Qt::ImageConversionFlags flags) override;
+
+ void copy(const QPlatformPixmap *data, const QRect &rect) override;
+ bool scroll(int dx, int dy, const QRect &rect) override;
+ void fill(const QColor &color) override;
+ bool hasAlphaChannel() const override;
+ QImage toImage() const override;
+ QImage toImage(const QRect &rect) const override;
+ QPaintEngine* paintEngine() const override;
+ QImage* buffer() override;
+ qreal devicePixelRatio() const override;
+ void setDevicePixelRatio(qreal scaleFactor) override;
protected:
- int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
void createPixmapForImage(QImage sourceImage, Qt::ImageConversionFlags flags);
void setImage(const QImage &image);
QImage image;
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 742aa31ba9..4b8b1203d6 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -193,7 +193,7 @@ public:
QPMCache();
~QPMCache();
- void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
+ 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);
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 856b82f559..ea10ab1b76 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -56,7 +56,7 @@ public:
Key();
Key(const Key &other);
#ifdef Q_COMPILER_RVALUE_REFS
- Key(Key &&other) Q_DECL_NOTHROW : d(other.d) { other.d = Q_NULLPTR; }
+ Key(Key &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
Key &operator =(Key &&other) Q_DECL_NOTHROW { swap(other); return *this; }
#endif
~Key();
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index b3b9f79fb1..2209c3de4d 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -163,6 +163,82 @@ bool QPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
return false;
}
+QBitmap QPlatformPixmap::mask() const
+{
+ if (!hasAlphaChannel())
+ return QBitmap();
+
+ const 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 int w = image.width();
+ const int h = image.height();
+
+ QImage mask(w, h, QImage::Format_MonoLSB);
+ if (mask.isNull()) // allocation failed
+ return QBitmap();
+
+ mask.setColorCount(2);
+ mask.setColor(0, QColor(Qt::color0).rgba());
+ mask.setColor(1, QColor(Qt::color1).rgba());
+
+ const int bpl = mask.bytesPerLine();
+
+ for (int y = 0; y < h; ++y) {
+ const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
+ uchar *dest = mask.scanLine(y);
+ memset(dest, 0, bpl);
+ for (int x = 0; x < w; ++x) {
+ if (qAlpha(*src) > 0)
+ dest[x >> 3] |= (1 << (x & 7));
+ ++src;
+ }
+ }
+
+ return QBitmap::fromImage(mask);
+}
+
+void QPlatformPixmap::setMask(const QBitmap &mask)
+{
+ QImage image = toImage();
+ if (mask.size().isEmpty()) {
+ if (image.depth() != 1) { // hw: ????
+ image = image.convertToFormat(QImage::Format_RGB32);
+ }
+ } else {
+ const int w = image.width();
+ const int h = image.height();
+
+ switch (image.depth()) {
+ case 1: {
+ const QImage imageMask = mask.toImage().convertToFormat(image.format());
+ for (int y = 0; y < h; ++y) {
+ const uchar *mscan = imageMask.scanLine(y);
+ uchar *tscan = image.scanLine(y);
+ int bytesPerLine = image.bytesPerLine();
+ for (int i = 0; i < bytesPerLine; ++i)
+ tscan[i] &= mscan[i];
+ }
+ break;
+ }
+ default: {
+ const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
+ image = 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);
+ for (int x = 0; x < w; ++x) {
+ if (!(mscan[x>>3] & (1 << (x&7))))
+ tscan[x] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ fromImage(image, Qt::AutoColor);
+}
+
QPixmap QPlatformPixmap::transformed(const QTransform &matrix,
Qt::TransformationMode mode) const
{
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 8513755cca..7635ac2949 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -69,7 +69,7 @@ public:
enum ClassId { RasterClass, DirectFBClass,
BlitterClass, Direct2DClass,
- CustomClass = 1024 };
+ X11Class, CustomClass = 1024 };
QPlatformPixmap(PixelType pixelType, int classId);
virtual ~QPlatformPixmap();
@@ -99,6 +99,9 @@ public:
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
+ virtual QBitmap mask() const;
+ virtual void setMask(const QBitmap &mask);
+
virtual bool hasAlphaChannel() const = 0;
virtual QPixmap transformed(const QTransform &matrix,
Qt::TransformationMode mode) const;
@@ -144,6 +147,7 @@ protected:
private:
friend class QPixmap;
+ friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
friend class QOpenGLTextureCache; //Needs to check the reference count
friend class QExplicitlySharedDataPointer<QPlatformPixmap>;
@@ -159,7 +163,7 @@ private:
# define QT_XFORM_TYPE_MSBFIRST 0
# define QT_XFORM_TYPE_LSBFIRST 1
-extern bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, int, int, int, const uchar*, int, int, int);
+Q_GUI_EXPORT bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, int, int, int, const uchar*, int, int, int);
QT_END_NAMESPACE
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index ce7f7b8a0f..9c54b9ada4 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -42,6 +42,7 @@
#ifndef QT_NO_IMAGEFORMAT_XPM
#include <private/qcolor_p.h>
+#include <qbytearraymatcher.h>
#include <qimage.h>
#include <qmap.h>
#include <qtextstream.h>
@@ -1041,7 +1042,9 @@ bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source,
if ((readBytes = device->readLine(buf.data(), buf.size())) < 0)
return false;
- if (buf.indexOf("/* XPM") != 0) {
+ static Q_RELAXED_CONSTEXPR auto matcher = qMakeStaticByteArrayMatcher("/* XPM");
+
+ if (matcher.indexIn(buf) != 0) {
while (readBytes > 0) {
device->ungetChar(buf.at(readBytes - 1));
--readBytes;