diff options
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/qiconloader.cpp | 14 | ||||
-rw-r--r-- | src/gui/image/qiconloader_p.h | 3 | ||||
-rw-r--r-- | src/gui/image/qimagewriter.cpp | 10 | ||||
-rw-r--r-- | src/gui/image/qimagewriter.h | 3 | ||||
-rw-r--r-- | src/gui/image/qpixmap.cpp | 71 | ||||
-rw-r--r-- | src/gui/image/qplatformpixmap.cpp | 76 | ||||
-rw-r--r-- | src/gui/image/qplatformpixmap.h | 3 |
7 files changed, 102 insertions, 78 deletions
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index d72c05a3c5..1d700446a9 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; @@ -651,7 +651,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) @@ -715,7 +715,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); @@ -764,7 +764,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/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/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..1857856b07 100644 --- a/src/gui/image/qplatformpixmap.h +++ b/src/gui/image/qplatformpixmap.h @@ -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; |