diff options
Diffstat (limited to 'src/gui/image')
35 files changed, 508 insertions, 217 deletions
diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h index f3ad90be20..be693af1cf 100644 --- a/src/gui/image/qbitmap.h +++ b/src/gui/image/qbitmap.h @@ -48,7 +48,7 @@ public: QBitmap(const QPixmap &); QBitmap(int w, int h); explicit QBitmap(const QSize &); - explicit QBitmap(const QString &fileName, const char *format=0); + explicit QBitmap(const QString &fileName, const char *format = Q_NULLPTR); ~QBitmap(); QBitmap &operator=(const QPixmap &); diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index 66bb77795e..d9e1347e4b 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtGui module of the Qt Toolkit. @@ -45,11 +46,7 @@ #include "qcache.h" #include "qdebug.h" #include "qpalette.h" - -#ifdef Q_DEAD_CODE_FROM_QT4_MAC -#include <private/qt_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif +#include "qmath.h" #include "private/qhexstring_p.h" #include "private/qguiapplication_p.h" @@ -134,7 +131,8 @@ static qreal qt_effective_device_pixel_ratio(QWindow *window = 0) QIconPrivate::QIconPrivate() : engine(0), ref(1), serialNum(serialNumCounter.fetchAndAddRelaxed(1)), - detach_no(0) + detach_no(0), + is_mask(false) { } @@ -362,7 +360,7 @@ static inline int origIcoDepth(const QImage &image) return s.isEmpty() ? 32 : s.toInt(); } -static inline int findBySize(const QList<QImage> &images, const QSize &size) +static inline int findBySize(const QVector<QImage> &images, const QSize &size) { for (int i = 0; i < images.size(); ++i) { if (images.at(i).size() == size) @@ -426,7 +424,7 @@ void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIco // these files may contain low-resolution images. As this information is lost, // ICOReader sets the original format as an image text key value. Read all matching // images into a list trying to find the highest quality per size. - QList<QImage> icoImages; + QVector<QImage> icoImages; while (imageReader.read(&image)) { if (ignoreSize || image.size() == size) { const int position = findBySize(icoImages, image.size()); @@ -599,6 +597,8 @@ QFactoryLoader *qt_iconEngineFactoryLoader() \image icon.png QIcon + \note QIcon needs a QGuiApplication instance before the icon is created. + \sa {fowler}{GUI Design Handbook: Iconic Label}, {Icons Example} */ @@ -1028,19 +1028,13 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State } else { detach(); } + d->engine->addFile(fileName, size, mode, state); - // Check if a "@2x" file exists and add it. - static bool disable2xImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING"); - if (!disable2xImageLoading && qApp->devicePixelRatio() > 1.0) { - QString at2xfileName = fileName; - int dotIndex = fileName.lastIndexOf(QLatin1Char('.')); - if (dotIndex == -1) /* no dot */ - dotIndex = fileName.size(); /* append */ - at2xfileName.insert(dotIndex, QStringLiteral("@2x")); - if (QFile::exists(at2xfileName)) - d->engine->addFile(at2xfileName, size, mode, state); - } + // Check if a "@Nx" file exists and add it. + QString atNxFileName = qt_findAtNxFile(fileName, qApp->devicePixelRatio()); + if (atNxFileName != fileName) + d->engine->addFile(atNxFileName, size, mode, state); } /*! @@ -1185,8 +1179,6 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback) qtIconCache()->insert(name, cachedIcon); } - // Note the qapp check is to allow lazy loading of static icons - // Supporting fallbacks will not work for this case. if (qApp && icon.availableSizes().isEmpty()) return fallback; @@ -1208,6 +1200,39 @@ bool QIcon::hasThemeIcon(const QString &name) return icon.name() == name; } +/*! + \since 5.6 + + Indicate that this icon is a mask image, and hence can potentially + be modified based on where it's displayed. + \sa isMask() +*/ +void QIcon::setIsMask(bool isMask) +{ + if (!d) { + d = new QIconPrivate; + d->engine = new QPixmapIconEngine; + } else { + detach(); + } + d->is_mask = isMask; +} + +/*! + \since 5.6 + + Returns \c true if this icon has been marked as a mask image. + Certain platforms render mask icons differently (for example, + menu icons on OS X). + + \sa setIsMask() +*/ +bool QIcon::isMask() const +{ + if (!d) + return false; + return d->is_mask; +} /***************************************************************************** QIcon stream functions @@ -1354,5 +1379,46 @@ QDebug operator<<(QDebug dbg, const QIcon &i) \internal */ +/*! + \internal + \since 5.6 + Attempts to find a suitable @Nx file for the given \a targetDevicePixelRatio + Returns the the \a baseFileName if no such file was found. + + Given base foo.png and a target dpr of 2.5, this function will look for + foo@3x.png, then foo@2x, then fall back to foo.png if not found. + + \a sourceDevicePixelRatio will be set to the value of N if the argument is + a non-null pointer +*/ +QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRatio, + qreal *sourceDevicePixelRatio) +{ + if (targetDevicePixelRatio <= 1.0) + return baseFileName; + + static bool disableNxImageLoading = !qEnvironmentVariableIsEmpty("QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING"); + if (disableNxImageLoading) + return baseFileName; + + int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.')); + if (dotIndex == -1) /* no dot */ + dotIndex = baseFileName.size(); /* append */ + + QString atNxfileName = baseFileName; + atNxfileName.insert(dotIndex, QLatin1String("@2x")); + // Check for @Nx, ..., @3x, @2x file versions, + for (int n = qMin(qCeil(targetDevicePixelRatio), 9); n > 1; --n) { + atNxfileName[dotIndex + 1] = QLatin1Char('0' + n); + if (QFile::exists(atNxfileName)) { + if (sourceDevicePixelRatio) + *sourceDevicePixelRatio = n; + return atNxfileName; + } + } + + return baseFileName; +} + QT_END_NAMESPACE #endif //QT_NO_ICON diff --git a/src/gui/image/qicon.h b/src/gui/image/qicon.h index 63e77eef99..9ed7336502 100644 --- a/src/gui/image/qicon.h +++ b/src/gui/image/qicon.h @@ -56,8 +56,8 @@ public: QIcon(const QIcon &other); #ifdef Q_COMPILER_RVALUE_REFS QIcon(QIcon &&other) Q_DECL_NOEXCEPT - : d(0) - { qSwap(d, other.d); } + : d(other.d) + { other.d = Q_NULLPTR; } #endif explicit QIcon(const QString &fileName); // file or resource name explicit QIcon(QIconEngine *engine); @@ -65,7 +65,7 @@ public: QIcon &operator=(const QIcon &other); #ifdef Q_COMPILER_RVALUE_REFS inline QIcon &operator=(QIcon &&other) Q_DECL_NOEXCEPT - { qSwap(d, other.d); return *this; } + { swap(other); return *this; } #endif inline void swap(QIcon &other) Q_DECL_NOEXCEPT { qSwap(d, other.d); } @@ -102,6 +102,9 @@ public: QList<QSize> availableSizes(Mode mode = Normal, State state = Off) const; + void setIsMask(bool isMask); + bool isMask() const; + static QIcon fromTheme(const QString &name, const QIcon &fallback = QIcon()); static bool hasThemeIcon(const QString &name); @@ -136,6 +139,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QIcon &); 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); + QT_END_NAMESPACE #endif // QICON_H diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index 8b42e770fa..2a4f584a0d 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -71,6 +71,7 @@ public: QAtomicInt ref; int serialNum; int detach_no; + bool is_mask; }; diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp index a25b216432..c09933d45f 100644 --- a/src/gui/image/qiconengine.cpp +++ b/src/gui/image/qiconengine.cpp @@ -77,6 +77,13 @@ QSize QIconEngine::actualSize(const QSize &size, QIcon::Mode /*mode*/, QIcon::St return size; } +/*! + \since 5.6 + Constructs the icon engine. + */ +QIconEngine::QIconEngine() +{ +} /*! Destroys the icon engine. diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h index 735da863fd..9977113054 100644 --- a/src/gui/image/qiconengine.h +++ b/src/gui/image/qiconengine.h @@ -44,6 +44,7 @@ QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QIconEngine { public: + QIconEngine(); virtual ~QIconEngine(); virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0; virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state); diff --git a/src/gui/image/qiconengineplugin.h b/src/gui/image/qiconengineplugin.h index 66684c871d..b05969f283 100644 --- a/src/gui/image/qiconengineplugin.h +++ b/src/gui/image/qiconengineplugin.h @@ -48,7 +48,7 @@ class Q_GUI_EXPORT QIconEnginePlugin : public QObject { Q_OBJECT public: - QIconEnginePlugin(QObject *parent = 0); + QIconEnginePlugin(QObject *parent = Q_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 fa14c84e83..3ead72dfbb 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -42,15 +42,10 @@ #include <QtGui/QIconEngine> #include <QtGui/QPalette> #include <QtCore/QList> -#include <QtCore/QHash> #include <QtCore/QDir> #include <QtCore/QSettings> #include <QtGui/QPainter> -#ifdef Q_DEAD_CODE_FROM_QT4_MAC -#include <private/qt_cocoa_helpers_mac_p.h> -#endif - #include <private/qhexstring_p.h> QT_BEGIN_NAMESPACE @@ -73,9 +68,6 @@ QIconLoader::QIconLoader() : { } -// We lazily initialize the loader to make static icons -// work. Though we do not officially support this. - static inline QString systemThemeName() { if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { @@ -398,9 +390,6 @@ void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) { QSize pixmapSize = rect.size(); -#if defined(Q_DEAD_CODE_FROM_QT4_MAC) - pixmapSize *= qt_mac_get_scalefactor(); -#endif painter->drawPixmap(rect, pixmap(pixmapSize, mode, state)); } diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h index 5b0362e218..ccf0a9d438 100644 --- a/src/gui/image/qiconloader_p.h +++ b/src/gui/image/qiconloader_p.h @@ -76,7 +76,7 @@ struct QIconDirInfo short maxSize; short minSize; short threshold; - Type type : 4; + Type type; }; Q_DECLARE_TYPEINFO(QIconDirInfo, Q_MOVABLE_TYPE); diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 01cacad630..667b65431e 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -491,6 +491,10 @@ bool QImageData::checkForAlphaPixels() const \snippet code/src_gui_image_qimage.cpp 1 \endtable + For images with more than 8-bit per color-channel. The methods + setPixelColor() and pixelColor() can be used to set and get + with QColor values. + QImage also provide the scanLine() function which returns a pointer to the pixel data at the scanline with the given index, and the bits() function which returns a pointer to the first pixel @@ -1785,11 +1789,11 @@ void QImage::fill(const QColor &color) break; case QImage::Format_BGR30: case QImage::Format_A2BGR30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderBGR>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64())); break; case QImage::Format_RGB30: case QImage::Format_A2RGB30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderRGB>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64())); break; case QImage::Format_RGB16: fill((uint) qConvertRgb32To16(color.rgba())); @@ -2206,9 +2210,10 @@ int QImage::pixelIndex(int x, int y) const If the \a position is not valid, the results are undefined. \warning This function is expensive when used for massive pixel - manipulations. + manipulations. Use constBits() or constScanLine() when many + pixels needs to be read. - \sa setPixel(), valid(), {QImage#Pixel Manipulation}{Pixel + \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel Manipulation} */ @@ -2219,12 +2224,12 @@ int QImage::pixelIndex(int x, int y) const */ QRgb QImage::pixel(int x, int y) const { - if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) { + if (!d || x < 0 || x >= d->width || y < 0 || y >= d->height) { qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y); return 12345; } - const uchar * s = constScanLine(y); + const uchar *s = d->data + y * d->bytes_per_line; switch(d->format) { case Format_Mono: return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1); @@ -2258,25 +2263,23 @@ QRgb QImage::pixel(int x, int y) const return *layout->convertToARGB32PM(&result, ptr, 1, layout, 0); } - /*! \fn void QImage::setPixel(const QPoint &position, uint index_or_rgb) Sets the pixel index or color at the given \a position to \a index_or_rgb. - If the image's format is either monochrome or 8-bit, the given \a + If the image's format is either monochrome or paletted, the given \a index_or_rgb value must be an index in the image's color table, otherwise the parameter must be a QRgb value. If \a position is not a valid coordinate pair in the image, or if \a index_or_rgb >= colorCount() in the case of monochrome and - 8-bit images, the result is undefined. + paletted images, the result is undefined. \warning This function is expensive due to the call of the internal \c{detach()} function called within; if performance is a concern, we - recommend the use of \l{QImage::}{scanLine()} to access pixel data - directly. + recommend the use of scanLine() or bits() to access pixel data directly. \sa pixel(), {QImage#Pixel Manipulation}{Pixel Manipulation} */ @@ -2364,6 +2367,116 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } /*! + \fn QColor QImage::pixelColor(const QPoint &position) const + \since 5.6 + + Returns the color of the pixel at the given \a position as a QColor. + + If the \a position is not valid, an invalid QColor is returned. + + \warning This function is expensive when used for massive pixel + manipulations. Use constBits() or constScanLine() when many + pixels needs to be read. + + \sa setPixel(), valid(), constBits(), constScanLine(), {QImage#Pixel Manipulation}{Pixel + Manipulation} +*/ + +/*! + \overload + \since 5.6 + + Returns the color of the pixel at coordinates (\a x, \a y) as a QColor. +*/ +QColor QImage::pixelColor(int x, int y) const +{ + if (!d || x < 0 || x >= d->width || y < 0 || y >= height()) { + qWarning("QImage::pixelColor: coordinate (%d,%d) out of range", x, y); + return QColor(); + } + + QRgba64 c; + const uchar * s = constScanLine(y); + switch (d->format) { + case Format_BGR30: + case Format_A2BGR30_Premultiplied: + c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]); + break; + case Format_RGB30: + case Format_A2RGB30_Premultiplied: + c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]); + break; + default: + c = QRgba64::fromArgb32(pixel(x, y)); + break; + } + // QColor is always unpremultiplied + if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied) + c = c.unpremultiplied(); + return QColor(c); +} + +/*! + \fn void QImage::setPixelColor(const QPoint &position, const QColor &color) + \since 5.6 + + Sets the color at the given \a position to \a color. + + If \a position is not a valid coordinate pair in the image, or + the image's format is either monochrome or paletted, the result is undefined. + + \warning This function is expensive due to the call of the internal + \c{detach()} function called within; if performance is a concern, we + recommend the use of scanLine() or bits() to access pixel data directly. + + \sa pixel(), bits(), scanLine(), {QImage#Pixel Manipulation}{Pixel Manipulation} +*/ + +/*! + \overload + \since 5.6 + + Sets the pixel color at (\a x, \a y) to \a color. +*/ +void QImage::setPixelColor(int x, int y, const QColor &color) +{ + if (!d || x < 0 || x >= width() || y < 0 || y >= height() || !color.isValid()) { + qWarning("QImage::setPixelColor: coordinate (%d,%d) out of range", x, y); + return; + } + // QColor is always unpremultiplied + QRgba64 c = color.rgba64(); + if (!hasAlphaChannel()) + c.setAlpha(65535); + else if (qPixelLayouts[d->format].premultiplied) + c = c.premultiplied(); + // detach is called from within scanLine + uchar * s = scanLine(y); + switch (d->format) { + case Format_Mono: + case Format_MonoLSB: + case Format_Indexed8: + qWarning("QImage::setPixelColor: called on monochrome or indexed format"); + return; + case Format_BGR30: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000; + return; + case Format_A2BGR30_Premultiplied: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c); + return; + case Format_RGB30: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000; + return; + case Format_A2RGB30_Premultiplied: + ((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c); + return; + default: + setPixel(x, y, c.toArgb32()); + return; + } +} + +/*! Returns \c true if all the colors in the image are shades of gray (i.e. their red, green and blue components are equal); otherwise false. @@ -3808,6 +3921,10 @@ int QImage::metric(PaintDeviceMetric metric) const return d->devicePixelRatio; break; + case PdmDevicePixelRatioScaled: + return d->devicePixelRatio * QPaintDevice::devicePixelRatioFScale(); + break; + default: qWarning("QImage::metric(): Unhandled metric type %d", metric); break; @@ -4521,32 +4638,7 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode if (complex_xform || mode == Qt::SmoothTransformation) { if (d->format < QImage::Format_RGB32 || !hasAlphaChannel()) { - switch(d->format) { - case QImage::Format_RGB16: - target_format = Format_ARGB8565_Premultiplied; - break; - case QImage::Format_RGB555: - target_format = Format_ARGB8555_Premultiplied; - break; - case QImage::Format_RGB666: - target_format = Format_ARGB6666_Premultiplied; - break; - case QImage::Format_RGB444: - target_format = Format_ARGB4444_Premultiplied; - break; - case QImage::Format_RGBX8888: - target_format = Format_RGBA8888_Premultiplied; - break; - case QImage::Format_BGR30: - target_format = Format_A2BGR30_Premultiplied; - break; - case QImage::Format_RGB30: - target_format = Format_A2RGB30_Premultiplied; - break; - default: - target_format = Format_ARGB32_Premultiplied; - break; - } + target_format = qt_alphaVersion(d->format); } } diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 26057f366c..888c7beb32 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -34,10 +34,11 @@ #ifndef QIMAGE_H #define QIMAGE_H -#include <QtGui/qtransform.h> -#include <QtGui/qpaintdevice.h> +#include <QtGui/qcolor.h> #include <QtGui/qrgb.h> +#include <QtGui/qpaintdevice.h> #include <QtGui/qpixelformat.h> +#include <QtGui/qtransform.h> #include <QtCore/qbytearray.h> #include <QtCore/qrect.h> #include <QtCore/qstring.h> @@ -124,15 +125,15 @@ 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 = 0, void *cleanupInfo = 0); - QImage(const uchar *data, int width, int height, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); - QImage(uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); - QImage(const uchar *data, int width, int height, int bytesPerLine, Format format, QImageCleanupFunction cleanupFunction = 0, void *cleanupInfo = 0); + 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); #ifndef QT_NO_IMAGEFORMAT_XPM explicit QImage(const char * const xpm[]); #endif - explicit QImage(const QString &fileName, const char *format = 0); + explicit QImage(const QString &fileName, const char *format = Q_NULLPTR); QImage(const QImage &); #ifdef Q_COMPILER_RVALUE_REFS @@ -220,6 +221,12 @@ public: void setPixel(int x, int y, uint index_or_rgb); void setPixel(const QPoint &pt, uint index_or_rgb); + QColor pixelColor(int x, int y) const; + QColor pixelColor(const QPoint &pt) const; + + void setPixelColor(int x, int y, const QColor &c); + void setPixelColor(const QPoint &pt, const QColor &c); + QVector<QRgb> colorTable() const; #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void setColorTable(const QVector<QRgb> &colors); @@ -272,16 +279,16 @@ public: bool load(QIODevice *device, const char* format); - bool load(const QString &fileName, const char* format=0); - bool loadFromData(const uchar *buf, int len, const char *format = 0); - inline bool loadFromData(const QByteArray &data, const char* aformat=0) + 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) { return loadFromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), aformat); } - bool save(const QString &fileName, const char* format=0, int quality=-1) const; - bool save(QIODevice *device, const char* format=0, int quality=-1) const; + 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; - static QImage fromData(const uchar *data, int size, const char *format = 0); - inline static QImage fromData(const QByteArray &data, const char *format = 0) + 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) { return fromData(reinterpret_cast<const uchar *>(data.constData()), data.size(), format); } #if QT_DEPRECATED_SINCE(5, 0) @@ -352,6 +359,8 @@ inline bool QImage::valid(const QPoint &pt) const { return valid(pt.x(), pt.y()) inline int QImage::pixelIndex(const QPoint &pt) const { return pixelIndex(pt.x(), pt.y());} inline QRgb QImage::pixel(const QPoint &pt) const { return pixel(pt.x(), pt.y()); } inline void QImage::setPixel(const QPoint &pt, uint index_or_rgb) { setPixel(pt.x(), pt.y(), index_or_rgb); } +inline QColor QImage::pixelColor(const QPoint &pt) const { return pixelColor(pt.x(), pt.y()); } +inline void QImage::setPixelColor(const QPoint &pt, const QColor &c) { setPixelColor(pt.x(), pt.y(), c); } #if QT_DEPRECATED_SINCE(5, 0) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 02f32aa34b..cc79e73534 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -375,7 +375,32 @@ static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::I } } +#ifdef __SSE2__ extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); +#else +static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data,Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888); + + const int pad = (data->bytes_per_line >> 2) - data->width; + QRgb *rgb_data = (QRgb *) data->data; + + for (int i = 0; i < data->height; ++i) { + const QRgb *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = qPremultiply(*rgb_data); + ++rgb_data; + } + rgb_data += pad; + } + + if (data->format == QImage::Format_ARGB32) + data->format = QImage::Format_ARGB32_Premultiplied; + else + data->format = QImage::Format_RGBA8888_Premultiplied; + return true; +} +#endif static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { @@ -2592,7 +2617,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma #ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, #else - 0, + convert_ARGB_to_ARGB_PM_inplace, #endif 0, 0, @@ -2705,12 +2730,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, mask_alpha_converter_rgbx_inplace, -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__ 0, +#ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, +#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN + convert_ARGB_to_ARGB_PM_inplace, #else 0, - 0, #endif 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888 @@ -2894,7 +2920,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma } // Format_Grayscale8 }; -void qInitImageConversions() +static void qInitImageConversions() { #if defined(__SSE2__) && defined(QT_COMPILER_SUPPORTS_SSSE3) if (qCpuHasFeature(SSSE3)) { @@ -2921,7 +2947,7 @@ void qInitImageConversions() } #endif -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; @@ -2941,4 +2967,6 @@ void qInitImageConversions() #endif } +Q_CONSTRUCTOR_FUNCTION(qInitImageConversions); + QT_END_NAMESPACE diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp index b51c43aa9d..5853510ee1 100644 --- a/src/gui/image/qimage_neon.cpp +++ b/src/gui/image/qimage_neon.cpp @@ -35,7 +35,7 @@ #include <private/qimage_p.h> #include <private/qsimd_p.h> -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) QT_BEGIN_NAMESPACE @@ -55,6 +55,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons if ((len - offsetToAlignOn8Bytes) >= 8) { const quint32 *const simdEnd = end - 7; +#if !defined(Q_PROCESSOR_ARM_64) register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff); do { #if Q_BYTE_ORDER == Q_BIG_ENDIAN @@ -76,6 +77,31 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons ); #endif } while (dst < simdEnd); +#else + register uint8x8_t fullVector asm ("v3") = vdup_n_u8(0xff); + do { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + asm volatile ( + "ld3 { v4.8b, v5.8b, v6.8b }, [%[SRC]], #24 \n\t" + "st4 { v3.8b, v4.8b, v5.8b, v6.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v4", "v5", "v6" + ); +#else + asm volatile ( + "ld3 { v0.8b, v1.8b, v2.8b }, [%[SRC]], #24 \n\t" + "mov v4.8b, v2.8b\n\t" + "mov v2.8b, v0.8b\n\t" + "mov v0.8b, v4.8b\n\t" + "st4 { v0.8b, v1.8b, v2.8b, v3.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v0", "v1", "v2", "v4" + ); +#endif + } while (dst < simdEnd); +#endif } while (dst != end) { @@ -103,4 +129,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I QT_END_NAMESPACE -#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#endif // defined(__ARM_NEON__) diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h index feeab60abd..f9ad6c0ac0 100644 --- a/src/gui/image/qimage_p.h +++ b/src/gui/image/qimage_p.h @@ -111,8 +111,6 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im void dither_to_Mono(QImageData *dst, const QImageData *src, Qt::ImageConversionFlags flags, bool fromalpha); -void qInitImageConversions(); - const uchar *qt_get_bitflip_array(); Q_GUI_EXPORT void qGamma_correct_back_to_linear_cs(QImage *image); @@ -163,10 +161,45 @@ inline int qt_depthForFormat(QImage::Format format) } return depth; } + #if defined(_M_ARM) #pragma optimize("", on) #endif +inline QImage::Format qt_alphaVersion(QImage::Format format) +{ + switch (format) { + case QImage::Format_RGB16: + return QImage::Format_ARGB8565_Premultiplied; + case QImage::Format_RGB555: + return QImage::Format_ARGB8555_Premultiplied; + case QImage::Format_RGB666: + return QImage::Format_ARGB6666_Premultiplied; + case QImage::Format_RGB444: + return QImage::Format_ARGB4444_Premultiplied; + case QImage::Format_RGBX8888: + return QImage::Format_RGBA8888_Premultiplied; + case QImage::Format_BGR30: + return QImage::Format_A2BGR30_Premultiplied; + case QImage::Format_RGB30: + return QImage::Format_A2RGB30_Premultiplied; + default: + break; + } + return QImage::Format_ARGB32_Premultiplied; +} + +inline QImage::Format qt_alphaVersionForPainting(QImage::Format format) +{ + QImage::Format toFormat = qt_alphaVersion(format); +#if defined(__ARM_NEON__) || defined(__SSE2__) + // If we are switching depth anyway and we have optimized ARGB32PM routines, upgrade to that. + if (qt_depthForFormat(format) != qt_depthForFormat(toFormat)) + toFormat = QImage::Format_ARGB32_Premultiplied; +#endif + return toFormat; +} + QT_END_NAMESPACE #endif // QIMAGE_P_H diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h index 80cd87c4c3..47a8a2b7c6 100644 --- a/src/gui/image/qimageiohandler.h +++ b/src/gui/image/qimageiohandler.h @@ -133,7 +133,7 @@ class Q_GUI_EXPORT QImageIOPlugin : public QObject { Q_OBJECT public: - explicit QImageIOPlugin(QObject *parent = 0); + explicit QImageIOPlugin(QObject *parent = Q_NULLPTR); virtual ~QImageIOPlugin(); enum Capability { diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index a35442308f..0ef587f333 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -252,7 +252,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, #ifdef QIMAGEREADER_DEBUG qDebug() << "QImageReader::createReadHandler( device =" << (void *)device << ", format =" << format << ")," - << keyMap.values().size() << "plugins available: " << keyMap.values(); + << keyMap.size() << "plugins available: " << keyMap.values(); #endif int suffixPluginIndex = -1; @@ -312,7 +312,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, const qint64 pos = device ? device->pos() : 0; if (autoDetectImageFormat) { - const int keyCount = keyMap.keys().size(); + const int keyCount = keyMap.size(); for (int i = 0; i < keyCount; ++i) { if (i != suffixPluginIndex) { QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i)); @@ -392,7 +392,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) { // check if any of our plugins recognize the file from its contents. const qint64 pos = device ? device->pos() : 0; - const int keyCount = keyMap.keys().size(); + const int keyCount = keyMap.size(); for (int i = 0; i < keyCount; ++i) { if (i != suffixPluginIndex) { QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i)); @@ -1168,7 +1168,8 @@ QImageIOHandler::Transformations QImageReader::transformation() const /*! \since 5.5 - Sets if images returned by read() should have transformation metadata automatically applied. + Determines that images returned by read() should have transformation metadata automatically + applied if \a enabled is \c true. \sa autoTransform(), transformation(), read() */ @@ -1203,6 +1204,39 @@ bool QImageReader::autoTransform() const } /*! + \since 5.6 + + This is an image format specific function that forces images with + gamma information to be gamma corrected to \a gamma. For image formats + that do not support gamma correction, this value is ignored. + + To gamma correct to a standard PC color-space, set gamma to \c 1/2.2. + + \sa gamma() +*/ +void QImageReader::setGamma(float gamma) +{ + if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::Gamma)) + d->handler->setOption(QImageIOHandler::Gamma, gamma); +} + +/*! + \since 5.6 + + Returns the gamma level of the decoded image. If setGamma() has been + called and gamma correction is supported it will return the gamma set. + If gamma level is not supported by the image format, \c 0.0 is returned. + + \sa setGamma() +*/ +float QImageReader::gamma() const +{ + if (d->initHandler() && d->handler->supportsOption(QImageIOHandler::Gamma)) + return d->handler->option(QImageIOHandler::Gamma).toFloat(); + return 0.0; +} + +/*! Returns \c true if an image can be read for the device (i.e., the image format is supported, and the device seems to contain valid data); otherwise returns \c false. diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h index 27a29bed49..6745c55b97 100644 --- a/src/gui/image/qimagereader.h +++ b/src/gui/image/qimagereader.h @@ -110,6 +110,9 @@ public: void setAutoTransform(bool enabled); bool autoTransform() const; + void setGamma(float gamma); + float gamma() const; + QByteArray subType() const; QList<QByteArray> supportedSubTypes() const; diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index e9de1db4b2..1cf75d8688 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -212,7 +212,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device, #ifndef QT_NO_IMAGEFORMATPLUGIN if (!testFormat.isEmpty()) { - const int keyCount = keyMap.keys().size(); + const int keyCount = keyMap.size(); for (int i = 0; i < keyCount; ++i) { QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(l->instance(i)); if (plugin && (plugin->capabilities(device, testFormat) & QImageIOPlugin::CanWrite)) { @@ -621,7 +621,7 @@ bool QImageWriter::progressiveScanWrite() const /*! \since 5.5 - Sets the image transformations metadata including orientation. + Sets the image transformations metadata including orientation to \a transform. If transformation metadata is not supported by the image format, the transform is applied before writing. diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index e29f9783a6..68709b708d 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -68,6 +68,7 @@ extern "C" { } QT_BEGIN_NAMESPACE +QT_WARNING_DISABLE_GCC("-Wclobbered") Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dst, const uchar *src, int len); typedef void (QT_FASTCALL *Rgb888ToRgb32Converter)(quint32 *dst, const uchar *src, int len); @@ -977,9 +978,8 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) { -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) // from qimage_neon.cpp - if (qCpuHasFeature(NEON)) d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; #endif diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h index 13bc381f8e..a750e4a9fc 100644 --- a/src/gui/image/qmovie.h +++ b/src/gui/image/qmovie.h @@ -73,9 +73,9 @@ public: }; Q_ENUM(CacheMode) - explicit QMovie(QObject *parent = 0); - explicit QMovie(QIODevice *device, const QByteArray &format = QByteArray(), QObject *parent = 0); - explicit QMovie(const QString &fileName, const QByteArray &format = QByteArray(), QObject *parent = 0); + 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); ~QMovie(); static QList<QByteArray> supportedFormats(); diff --git a/src/gui/image/qpaintengine_pic.cpp b/src/gui/image/qpaintengine_pic.cpp index 9ab1e2c30b..47480ebbae 100644 --- a/src/gui/image/qpaintengine_pic.cpp +++ b/src/gui/image/qpaintengine_pic.cpp @@ -398,6 +398,7 @@ void QPicturePaintEngine::drawPolygon(const QPointF *points, int numPoints, Poly int pos; QPolygonF polygon; + polygon.reserve(numPoints); for (int i=0; i<numPoints; ++i) polygon << points[i]; diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp index b63be19153..2b184466f4 100644 --- a/src/gui/image/qpicture.cpp +++ b/src/gui/image/qpicture.cpp @@ -961,6 +961,9 @@ int QPicture::metric(PaintDeviceMetric m) const case PdmDevicePixelRatio: val = 1; break; + case PdmDevicePixelRatioScaled: + val = 1 * QPaintDevice::devicePixelRatioFScale(); + break; default: val = 0; qWarning("QPicture::metric: Invalid metric command"); @@ -1216,7 +1219,9 @@ QList<QByteArray> QPicture::inputFormats() static QStringList qToStringList(const QList<QByteArray> &arr) { QStringList list; - for (int i = 0; i < arr.count(); ++i) + const int count = arr.count(); + list.reserve(count); + for (int i = 0; i < count; ++i) list.append(QString::fromLatin1(arr.at(i))); return list; } diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h index c3897a1935..a71d1deb02 100644 --- a/src/gui/image/qpicture.h +++ b/src/gui/image/qpicture.h @@ -62,10 +62,10 @@ public: bool play(QPainter *p); - bool load(QIODevice *dev, const char *format = 0); - bool load(const QString &fileName, const char *format = 0); - bool save(QIODevice *dev, const char *format = 0); - bool save(const QString &fileName, const char *format = 0); + 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); QRect boundingRect() const; void setBoundingRect(const QRect &r); diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h index 56e6e1249c..a414a122f1 100644 --- a/src/gui/image/qpicture_p.h +++ b/src/gui/image/qpicture_p.h @@ -48,6 +48,7 @@ #include "QtCore/qatomic.h" #include "QtCore/qbuffer.h" #include "QtCore/qobjectdefs.h" +#include "QtCore/qvector.h" #include "QtGui/qpicture.h" #include "QtGui/qpixmap.h" #include "QtGui/qpen.h" @@ -150,8 +151,8 @@ public: QRect override_rect; QScopedPointer<QPaintEngine> paintEngine; bool in_memory_only; - QList<QImage> image_list; - QList<QPixmap> pixmap_list; + QVector<QImage> image_list; + QVector<QPixmap> pixmap_list; QList<QBrush> brush_list; QList<QPen> pen_list; }; diff --git a/src/gui/image/qpictureformatplugin.h b/src/gui/image/qpictureformatplugin.h index 773c0180d3..9ad938fa79 100644 --- a/src/gui/image/qpictureformatplugin.h +++ b/src/gui/image/qpictureformatplugin.h @@ -53,7 +53,7 @@ class Q_GUI_EXPORT QPictureFormatPlugin : public QObject { Q_OBJECT public: - explicit QPictureFormatPlugin(QObject *parent = 0); + explicit QPictureFormatPlugin(QObject *parent = Q_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 e53af8038f..fb62889e40 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -907,7 +907,7 @@ void QPixmap::fill(const QPaintDevice *device, const QPoint &p) { Q_UNUSED(device) Q_UNUSED(p) - qWarning("%s is deprecated, ignored", Q_FUNC_INFO); + qWarning("this function is deprecated, ignored"); } @@ -1703,8 +1703,8 @@ QPixmap QPixmap::fromImageReader(QImageReader *imageReader, Qt::ImageConversionF QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) { - qWarning("%s is deprecated, use QScreen::grabWindow() instead." - " Defaulting to primary screen.", Q_FUNC_INFO); + qWarning("this function is deprecated, use QScreen::grabWindow() instead." + " Defaulting to primary screen."); return QGuiApplication::primaryScreen()->grabWindow(window, x, y, w, h); } diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 51b02acfcf..48db7a3840 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -58,7 +58,7 @@ public: explicit QPixmap(QPlatformPixmap *data); QPixmap(int w, int h); explicit QPixmap(const QSize &); - QPixmap(const QString& fileName, const char *format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor); + QPixmap(const QString& fileName, const char *format = Q_NULLPTR, Qt::ImageConversionFlags flags = Qt::AutoColor); #ifndef QT_NO_IMAGEFORMAT_XPM explicit QPixmap(const char * const xpm[]); #endif @@ -131,19 +131,19 @@ public: } #endif - bool load(const QString& fileName, const char *format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor); - bool loadFromData(const uchar *buf, uint len, const char* format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor); - inline bool loadFromData(const QByteArray &data, const char* format = 0, Qt::ImageConversionFlags flags = Qt::AutoColor); - bool save(const QString& fileName, const char* format = 0, int quality = -1) const; - bool save(QIODevice* device, const char* format = 0, int quality = -1) const; + 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 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 = 0); - void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = 0); + 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); #if QT_DEPRECATED_SINCE(5, 0) QT_DEPRECATED inline int serialNumber() const { return cacheKey() >> 32; } diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index f24cbc3db9..b254c5a2af 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -115,6 +115,8 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con return qt_defaultDpiY(); case QPaintDevice::PdmDevicePixelRatio: return devicePixelRatio(); + case QPaintDevice::PdmDevicePixelRatioScaled: + return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale(); default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 9c8835a7a0..bbdf77355e 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -178,20 +178,7 @@ void QRasterPlatformPixmap::fill(const QColor &color) int alpha = color.alpha(); if (alpha != 255) { if (!image.hasAlphaChannel()) { - QImage::Format toFormat; -#if !(defined(__ARM_NEON__) || defined(__SSE2__)) - if (image.format() == QImage::Format_RGB16) - toFormat = QImage::Format_ARGB8565_Premultiplied; - else if (image.format() == QImage::Format_RGB666) - toFormat = QImage::Format_ARGB6666_Premultiplied; - else if (image.format() == QImage::Format_RGB555) - toFormat = QImage::Format_ARGB8555_Premultiplied; - else if (image.format() == QImage::Format_RGB444) - toFormat = QImage::Format_ARGB4444_Premultiplied; - else -#endif - toFormat = QImage::Format_ARGB32_Premultiplied; - + QImage::Format toFormat = qt_alphaVersionForPainting(image.format()); if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) { image.detach(); image.d->format = toFormat; @@ -288,6 +275,9 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const return qt_defaultDpiY(); case QPaintDevice::PdmDevicePixelRatio: return image.devicePixelRatio(); + case QPaintDevice::PdmDevicePixelRatioScaled: + return image.devicePixelRatio() * QPaintDevice::devicePixelRatioFScale(); + default: qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric); break; @@ -311,17 +301,7 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC : QImage::Format_RGB32; } else { QImage::Format opaqueFormat = QNativeImage::systemFormat(); - QImage::Format alphaFormat = QImage::Format_ARGB32_Premultiplied; - -#if !defined(__ARM_NEON__) && !defined(__SSE2__) - switch (opaqueFormat) { - case QImage::Format_RGB16: - alphaFormat = QImage::Format_ARGB8565_Premultiplied; - break; - default: // We don't care about the others... - break; - } -#endif + QImage::Format alphaFormat = qt_alphaVersionForPainting(opaqueFormat); if (!sourceImage.hasAlphaChannel()) { format = opaqueFormat; diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 12e19440dc..a7a9b375ff 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -345,9 +345,22 @@ static QImage qt_imageFromWinIconHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) return image; } +static inline bool hasAlpha(const QImage &image) +{ + const int w = image.width(); + const int h = image.height(); + for (int y = 0; y < h; ++y) { + const QRgb *scanLine = reinterpret_cast<const QRgb *>(image.scanLine(y)); + for (int x = 0; x < w; ++x) { + if (qAlpha(scanLine[x]) != 0) + return true; + } + } + return false; +} + Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) { - bool foundAlpha = false; HDC screenDevice = GetDC(0); HDC hdc = CreateCompatibleDC(screenDevice); ReleaseDC(0, screenDevice); @@ -356,6 +369,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) const bool result = GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center if (!result) { qErrnoWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()"); + DeleteDC(hdc); return QPixmap(); } @@ -371,17 +385,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL); QImage image = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h); - for (int y = 0 ; y < h && !foundAlpha ; y++) { - const QRgb *scanLine= reinterpret_cast<const QRgb *>(image.scanLine(y)); - for (int x = 0; x < w ; x++) { - if (qAlpha(scanLine[x]) != 0) { - foundAlpha = true; - break; - } - } - } - if (!foundAlpha) { - //If no alpha was found, we use the mask to set alpha values + if (!image.isNull() && !hasAlpha(image)) { //If no alpha was found, we use the mask to set alpha values DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK); const QImage mask = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h); diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 3836976975..d29ddcf978 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE memory. The \e{Qt Quarterly} article - \l{http://doc.qt.digia.com/qq/qq12-qpixmapcache.html}{Optimizing + \l{http://doc.qt.io/archives/qq/qq12-qpixmapcache.html}{Optimizing with QPixmapCache} explains how to use QPixmapCache to speed up applications by caching the results of painting. @@ -138,6 +138,24 @@ bool QPixmapCache::Key::operator ==(const Key &key) const */ /*! + \fn QPixmapCache::Key::Key(Key &&) + \internal + \since 5.6 +*/ + +/*! + \fn QPixmapCache::Key &QPixmapCache::Key::operator=(Key &&) + \internal + \since 5.6 +*/ + +/*! + \fn void QPixmapCache::Key::swap(Key &) + \internal + \since 5.6 +*/ + +/*! \internal */ QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other) @@ -179,7 +197,6 @@ public: static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key); - QList< QPair<QString,QPixmap> > allPixmaps() const; bool flushDetachedPixmaps(bool nt); private: @@ -423,20 +440,6 @@ QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key) return key->d; } -QList< QPair<QString,QPixmap> > QPMCache::allPixmaps() const -{ - QList< QPair<QString,QPixmap> > r; - QHash<QString, QPixmapCache::Key>::const_iterator it = cacheKeys.begin(); - while (it != cacheKeys.end()) { - QPixmap *ptr = QCache<QPixmapCache::Key, QPixmapCacheEntry>::object(it.value()); - if (ptr) - r.append(QPair<QString,QPixmap>(it.key(),*ptr)); - ++it; - } - return r; -} - - Q_GLOBAL_STATIC(QPMCache, pm_cache) int Q_AUTOTEST_EXPORT q_QPixmapCache_keyHashSize() @@ -639,7 +642,8 @@ void QPixmapCache::remove(const Key &key) void QPixmapCache::clear() { QT_TRY { - pm_cache()->clear(); + if (pm_cache.exists()) + pm_cache->clear(); } QT_CATCH(const std::bad_alloc &) { // if we ran out of memory during pm_cache(), it's no leak, // so just ignore it. @@ -656,10 +660,6 @@ int QPixmapCache::totalUsed() return (pm_cache()->totalCost()+1023) / 1024; } -QList< QPair<QString,QPixmap> > QPixmapCache::allPixmaps() -{ - return pm_cache()->allPixmaps(); -} /*! \fn QPixmapCache::KeyData::KeyData() @@ -667,7 +667,6 @@ QList< QPair<QString,QPixmap> > QPixmapCache::allPixmaps() */ /*! \fn QPixmapCache::KeyData::KeyData(const KeyData &other) - \internal */ /*! diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h index 345389e987..37a0588e06 100644 --- a/src/gui/image/qpixmapcache.h +++ b/src/gui/image/qpixmapcache.h @@ -36,10 +36,6 @@ #include <QtGui/qpixmap.h> -#ifdef Q_TEST_QPIXMAPCACHE -#include <QtCore/qpair.h> -#endif - QT_BEGIN_NAMESPACE @@ -52,12 +48,18 @@ public: 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 &operator =(Key &&other) Q_DECL_NOTHROW { swap(other); return *this; } +#endif ~Key(); bool operator ==(const Key &key) const; inline bool operator !=(const Key &key) const { return !operator==(key); } Key &operator =(const Key &other); + void swap(Key &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + private: KeyData *d; friend class QPMCache; @@ -80,9 +82,9 @@ public: #ifdef Q_TEST_QPIXMAPCACHE static void flushDetachedPixmaps(); static int totalUsed(); - static QList< QPair<QString,QPixmap> > allPixmaps(); #endif }; +Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QPixmapCache::Key) QT_END_NAMESPACE diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 7fbd24787e..e9944e1750 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -43,13 +43,8 @@ #include <qvariant.h> #include <qvector.h> -#ifdef QT_USE_BUNDLED_LIBPNG -#include <../../3rdparty/libpng/png.h> -#include <../../3rdparty/libpng/pngconf.h> -#else #include <png.h> #include <pngconf.h> -#endif #if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \ && defined(PNG_PEDANTIC_WARNINGS_SUPPORTED) @@ -108,10 +103,11 @@ public: }; QPngHandlerPrivate(QPngHandler *qq) - : gamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) + : gamma(0.0), fileGamma(0.0), quality(2), png_ptr(0), info_ptr(0), end_info(0), state(Ready), q(qq) { } float gamma; + float fileGamma; int quality; QString description; QSize scaledSize; @@ -234,13 +230,10 @@ void CALLBACK_CALL_TYPE qpiw_flush_fn(png_structp /* png_ptr */) } static -void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0) +void setup_qt(QImage& image, png_structp png_ptr, png_infop info_ptr, QSize scaledSize, bool *doScaledRead, float screen_gamma=0.0, float file_gamma=0.0) { - if (screen_gamma != 0.0 && png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { - double file_gamma; - png_get_gAMA(png_ptr, info_ptr, &file_gamma); - png_set_gamma(png_ptr, screen_gamma, file_gamma); - } + if (screen_gamma != 0.0 && file_gamma != 0.0) + png_set_gamma(png_ptr, 1.0f / screen_gamma, file_gamma); png_uint_32 width; png_uint_32 height; @@ -557,6 +550,12 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader() readPngTexts(info_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA)) { + double file_gamma = 0.0; + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + fileGamma = file_gamma; + } + state = ReadHeader; return true; } @@ -580,7 +579,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage) } bool doScaledRead = false; - setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma); + setup_qt(*outImage, png_ptr, info_ptr, scaledSize, &doScaledRead, gamma, fileGamma); if (outImage->isNull()) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); @@ -1063,7 +1062,7 @@ QVariant QPngHandler::option(ImageOption option) const return QVariant(); if (option == Gamma) - return d->gamma; + return d->gamma == 0.0 ? d->fileGamma : d->gamma; else if (option == Quality) return d->quality; else if (option == Description) diff --git a/src/gui/image/qpnghandler.pri b/src/gui/image/qpnghandler.pri index 9ab175d628..505d214130 100644 --- a/src/gui/image/qpnghandler.pri +++ b/src/gui/image/qpnghandler.pri @@ -1,9 +1,4 @@ HEADERS += $$PWD/qpnghandler_p.h SOURCES += $$PWD/qpnghandler.cpp -contains(QT_CONFIG, system-png) { - if(unix|mingw): LIBS_PRIVATE += -lpng - else:win32: LIBS += libpng.lib -} else { - include($$PWD/../../3rdparty/libpng.pri) -} +include($$PWD/../../3rdparty/png_dependency.pri) diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index f460431c2b..7f23656c02 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -46,13 +46,21 @@ QT_BEGIN_NAMESPACE PBM/PGM/PPM (ASCII and RAW) image read/write functions *****************************************************************************/ +static void discard_pbm_line(QIODevice *d) +{ + const int buflen = 100; + char buf[buflen]; + int res = 0; + do { + res = d->readLine(buf, buflen); + } while (res > 0 && buf[res-1] != '\n'); +} + static int read_pbm_int(QIODevice *d) { char c; int val = -1; bool digit; - const int buflen = 100; - char buf[buflen]; for (;;) { if (!d->getChar(&c)) // end of file break; @@ -63,7 +71,7 @@ static int read_pbm_int(QIODevice *d) continue; } else { if (c == '#') // comment - d->readLine(buf, buflen); + discard_pbm_line(d); break; } } @@ -72,7 +80,7 @@ static int read_pbm_int(QIODevice *d) else if (isspace((uchar) c)) continue; else if (c == '#') - (void)d->readLine(buf, buflen); + discard_pbm_line(d); else break; } |