summaryrefslogtreecommitdiffstats
path: root/src/gui/image
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/image')
-rw-r--r--src/gui/image/qicon.cpp7
-rw-r--r--src/gui/image/qiconloader.cpp14
-rw-r--r--src/gui/image/qiconloader_p.h3
-rw-r--r--src/gui/image/qimage_conversions.cpp36
-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.h2
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpicture.h12
-rw-r--r--src/gui/image/qpixmap.cpp71
-rw-r--r--src/gui/image/qplatformpixmap.cpp76
-rw-r--r--src/gui/image/qplatformpixmap.h8
-rw-r--r--src/gui/image/qxpmhandler.cpp5
15 files changed, 209 insertions, 99 deletions
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index fa4b4e01af..9b2e96d4b0 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1469,8 +1469,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/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 349e0dfbe3..3cb6f46bd6 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -609,18 +609,18 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon
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 +630,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,7 +654,7 @@ 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)
@@ -718,7 +718,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);
@@ -767,7 +767,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..9398bca585 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -132,12 +132,13 @@ public:
bool read(QDataStream &in) Q_DECL_OVERRIDE;
bool write(QDataStream &out) const Q_DECL_OVERRIDE;
+ Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
+
private:
QString key() const Q_DECL_OVERRIDE;
bool hasIcon() const;
void ensureLoaded();
void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- QIconLoaderEngineEntry *entryForSize(const QSize &size, int scale = 1);
QIconLoaderEngine(const QIconLoaderEngine &other);
QThemeIconInfo m_info;
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 50fad1566c..aa7cfe9547 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);
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 381ddb5b45..7a5a630495 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -565,6 +565,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
@@ -575,7 +585,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 a1ca857daa..2ff9fb4e36 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..ca559d491b 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -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/qpicture.cpp b/src/gui/image/qpicture.cpp
index 7506e2e1a9..a9c3482209 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1194,6 +1194,7 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qpictureformatplugin.h"
QT_END_INCLUDE_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 0)
/*!
\obsolete
@@ -1279,6 +1280,7 @@ QList<QByteArray> QPicture::outputFormats()
{
return QPictureIO::outputFormats();
}
+#endif // QT_DEPRECATED_SINCE(5, 0)
/*****************************************************************************
QPictureIO member functions
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 8da11caee4..2d505d1d06 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -90,11 +90,13 @@ 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, 0)
+ 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, 0)
QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
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/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index 00c21a5f54..b123afb4db 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -160,6 +160,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;