diff options
Diffstat (limited to 'src/gui/image')
-rw-r--r-- | src/gui/image/image.pri | 2 | ||||
-rw-r--r-- | src/gui/image/qbitmap.cpp | 52 | ||||
-rw-r--r-- | src/gui/image/qbitmap.h | 1 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 74 | ||||
-rw-r--r-- | src/gui/image/qimage.h | 2 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 113 | ||||
-rw-r--r-- | src/gui/image/qimage_sse4.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qimagereader.cpp | 117 | ||||
-rw-r--r-- | src/gui/image/qimagereader.h | 1 | ||||
-rw-r--r-- | src/gui/image/qimagereaderwriterhelpers.cpp | 180 | ||||
-rw-r--r-- | src/gui/image/qimagereaderwriterhelpers_p.h | 139 | ||||
-rw-r--r-- | src/gui/image/qimagewriter.cpp | 121 | ||||
-rw-r--r-- | src/gui/image/qimagewriter.h | 1 | ||||
-rw-r--r-- | src/gui/image/qpixmap.cpp | 10 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 11 | ||||
-rw-r--r-- | src/gui/image/qpixmap_win.cpp | 388 | ||||
-rw-r--r-- | src/gui/image/qpixmapcache.cpp | 25 | ||||
-rw-r--r-- | src/gui/image/qxbmhandler.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qxpmhandler.cpp | 4 |
20 files changed, 817 insertions, 442 deletions
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 76aba944b2..b4942f06d4 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -9,6 +9,7 @@ HEADERS += \ image/qimage_p.h \ image/qimageiohandler.h \ image/qimagereader.h \ + image/qimagereaderwriterhelpers_p.h \ image/qimagewriter.h \ image/qpaintengine_pic_p.h \ image/qpicture.h \ @@ -33,6 +34,7 @@ SOURCES += \ image/qimage_conversions.cpp \ image/qimageiohandler.cpp \ image/qimagereader.cpp \ + image/qimagereaderwriterhelpers.cpp \ image/qimagewriter.cpp \ image/qpaintengine_pic.cpp \ image/qpicture.cpp \ diff --git a/src/gui/image/qbitmap.cpp b/src/gui/image/qbitmap.cpp index e8405a6d11..2453242fa8 100644 --- a/src/gui/image/qbitmap.cpp +++ b/src/gui/image/qbitmap.cpp @@ -189,9 +189,7 @@ QBitmap &QBitmap::operator=(const QPixmap &pixmap) } else if (pixmap.depth() == 1) { // 1-bit pixmap QPixmap::operator=(pixmap); // shallow assignment } else { // n-bit depth pixmap - QImage image; - image = pixmap.toImage(); // convert pixmap to image - *this = fromImage(image); // will dither image + *this = fromImage(pixmap.toImage()); // will dither image } return *this; } @@ -223,6 +221,24 @@ QBitmap::operator QVariant() const return QVariant(QVariant::Bitmap, this); } +static QBitmap makeBitmap(QImage &&image, Qt::ImageConversionFlags flags) +{ + // make sure image.color(0) == Qt::color0 (white) + // and image.color(1) == Qt::color1 (black) + const QRgb c0 = QColor(Qt::black).rgb(); + const QRgb c1 = QColor(Qt::white).rgb(); + if (image.color(0) == c0 && image.color(1) == c1) { + image.invertPixels(); + image.setColor(0, c1); + image.setColor(1, c0); + } + + QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType)); + + data->fromImageInPlace(image, flags | Qt::MonoOnly); + return QPixmap(data.take()); +} + /*! Returns a copy of the given \a image converted to a bitmap using the specified image conversion \a flags. @@ -234,22 +250,24 @@ QBitmap QBitmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags) if (image.isNull()) return QBitmap(); - QImage img = image.convertToFormat(QImage::Format_MonoLSB, flags); + return makeBitmap(image.convertToFormat(QImage::Format_MonoLSB, flags), flags); +} - // make sure image.color(0) == Qt::color0 (white) - // and image.color(1) == Qt::color1 (black) - const QRgb c0 = QColor(Qt::black).rgb(); - const QRgb c1 = QColor(Qt::white).rgb(); - if (img.color(0) == c0 && img.color(1) == c1) { - img.invertPixels(); - img.setColor(0, c1); - img.setColor(1, c0); - } +/*! + \since 5.12 + \overload - QScopedPointer<QPlatformPixmap> data(QGuiApplicationPrivate::platformIntegration()->createPlatformPixmap(QPlatformPixmap::BitmapType)); + Returns a copy of the given \a image converted to a bitmap using + the specified image conversion \a flags. - data->fromImage(img, flags | Qt::MonoOnly); - return QPixmap(data.take()); + \sa fromData() +*/ +QBitmap QBitmap::fromImage(QImage &&image, Qt::ImageConversionFlags flags) +{ + if (image.isNull()) + return QBitmap(); + + return makeBitmap(std::move(image).convertToFormat(QImage::Format_MonoLSB, flags), flags); } /*! @@ -277,7 +295,7 @@ QBitmap QBitmap::fromData(const QSize &size, const uchar *bits, QImage::Format m int bytesPerLine = (size.width() + 7) / 8; for (int y = 0; y < size.height(); ++y) memcpy(image.scanLine(y), bits + bytesPerLine * y, bytesPerLine); - return QBitmap::fromImage(image); + return QBitmap::fromImage(std::move(image)); } /*! diff --git a/src/gui/image/qbitmap.h b/src/gui/image/qbitmap.h index 6a8c8b3457..188064fccf 100644 --- a/src/gui/image/qbitmap.h +++ b/src/gui/image/qbitmap.h @@ -72,6 +72,7 @@ public: inline void clear() { fill(Qt::color0); } static QBitmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor); + static QBitmap fromImage(QImage &&image, Qt::ImageConversionFlags flags = Qt::AutoColor); static QBitmap fromData(const QSize &size, const uchar *bits, QImage::Format monoFormat = QImage::Format_MonoLSB); diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 7fcae12cbd..907f90f3a5 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -2303,8 +2303,7 @@ QRgb QImage::pixel(int x, int y) const } const QPixelLayout *layout = &qPixelLayouts[d->format]; uint result; - const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1); - return *layout->convertToARGB32PM(&result, ptr, 1, 0, 0); + return *layout->fetchToARGB32PM(&result, s, x, 1, nullptr, nullptr); } /*! @@ -2405,9 +2404,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } const QPixelLayout *layout = &qPixelLayouts[d->format]; - uint result; - const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, 0, 0); - qStorePixels[layout->bpp](s, ptr, x, 1); + layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr); } /*! @@ -2582,17 +2579,15 @@ bool QImage::allGray() const break; } - const int buffer_size = 2048; - uint buffer[buffer_size]; + uint buffer[BufferSize]; const QPixelLayout *layout = &qPixelLayouts[d->format]; - FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + const auto fetch = layout->fetchToARGB32PM; for (int j = 0; j < d->height; ++j) { const uchar *b = constScanLine(j); int x = 0; while (x < d->width) { - int l = qMin(d->width - x, buffer_size); - const uint *ptr = fetch(buffer, b, x, l); - ptr = layout->convertToARGB32PM(buffer, ptr, l, 0, 0); + int l = qMin(d->width - x, BufferSize); + const uint *ptr = fetch(buffer, b, x, l, nullptr, nullptr); for (int i = 0; i < l; ++i) { if (!qIsGray(ptr[i])) return false; @@ -3210,33 +3205,18 @@ void QImage::mirrored_inplace(bool horizontal, bool vertical) inline void rgbSwapped_generic(int width, int height, const QImage *src, QImage *dst, const QPixelLayout* layout) { - Q_ASSERT(layout->redWidth == layout->blueWidth); - FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; - StorePixelsFunc store = qStorePixels[layout->bpp]; - - const uint redBlueMask = (1 << layout->redWidth) - 1; - const uint alphaGreenMask = (((1 << layout->alphaWidth) - 1) << layout->alphaShift) - | (((1 << layout->greenWidth) - 1) << layout->greenShift); + const RbSwapFunc func = layout->rbSwap; + if (!func) { + qWarning("Trying to rb-swap an image format where it doesn't make sense"); + if (src != dst) + *dst = *src; + return; + } - const int buffer_size = 2048; - uint buffer[buffer_size]; for (int i = 0; i < height; ++i) { uchar *q = dst->scanLine(i); const uchar *p = src->constScanLine(i); - int x = 0; - while (x < width) { - int l = qMin(width - x, buffer_size); - const uint *ptr = fetch(buffer, p, x, l); - for (int j = 0; j < l; ++j) { - uint red = (ptr[j] >> layout->redShift) & redBlueMask; - uint blue = (ptr[j] >> layout->blueShift) & redBlueMask; - buffer[j] = (ptr[j] & alphaGreenMask) - | (red << layout->blueShift) - | (blue << layout->redShift); - } - store(q, buffer, x, l); - x += l; - } + func(q, p, width); } } @@ -3321,23 +3301,6 @@ QImage QImage::rgbSwapped_helper() const } } break; - case Format_BGR30: - case Format_A2BGR30_Premultiplied: - case Format_RGB30: - case Format_A2RGB30_Premultiplied: - 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) { - *q = qRgbSwapRgb30(*p); - p++; - q++; - } - } - break; default: res = QImage(d->width, d->height, d->format); rgbSwapped_generic(d->width, d->height, this, &res, &qPixelLayouts[d->format]); @@ -3457,8 +3420,7 @@ void QImage::rgbSwapped_inplace() bool QImage::load(const QString &fileName, const char* format) { - QImage image = QImageReader(fileName, format).read(); - operator=(image); + *this = QImageReader(fileName, format).read(); return !isNull(); } @@ -3471,8 +3433,7 @@ bool QImage::load(const QString &fileName, const char* format) bool QImage::load(QIODevice* device, const char* format) { - QImage image = QImageReader(device, format).read(); - operator=(image); + *this = QImageReader(device, format).read(); return !isNull(); } @@ -3492,8 +3453,7 @@ bool QImage::load(QIODevice* device, const char* format) bool QImage::loadFromData(const uchar *data, int len, const char *format) { - QImage image = fromData(data, len, format); - operator=(image); + *this = fromData(data, len, format); return !isNull(); } diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 9b76b62f24..1f39569dda 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -96,6 +96,7 @@ typedef void (*QImageCleanupFunction)(void*); class Q_GUI_EXPORT QImage : public QPaintDevice { + Q_GADGET public: enum InvertMode { InvertRgb, InvertRgba }; enum Format { @@ -132,6 +133,7 @@ public: NImageFormats #endif }; + Q_ENUM(Format) QImage() Q_DECL_NOEXCEPT; QImage(const QSize &size, Format format); diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 1b4d3e63dd..ce47b78682 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -118,26 +118,35 @@ void qGamma_correct_back_to_linear_cs(QImage *image) Internal routines for converting image depth. *****************************************************************************/ -// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion. -static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +// The drawhelper conversions from/to RGB32 are passthroughs which is not always correct for general image conversion +static void QT_FASTCALL storeRGB32FromARGB32PM(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + uint *d = reinterpret_cast<uint *>(dest) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply(src[i]); - return buffer; + d[i] = 0xff000000 | qUnpremultiply(src[i]); +} + +static void QT_FASTCALL storeRGB32FromARGB32(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) +{ + uint *d = reinterpret_cast<uint *>(dest) + index; + for (int i = 0; i < count; ++i) + d[i] = 0xff000000 | src[i]; } -static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +static const uint *QT_FASTCALL fetchRGB32ToARGB32PM(uint *buffer, const uchar *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + const uint *s = reinterpret_cast<const uint *>(src) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 |src[i]; + buffer[i] = 0xff000000 | s[i]; return buffer; } #ifdef QT_COMPILER_SUPPORTS_SSE4_1 -extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *); +extern void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *); #endif void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags) @@ -145,42 +154,39 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio // Cannot be used with indexed formats. Q_ASSERT(dest->format > QImage::Format_Indexed8); Q_ASSERT(src->format > QImage::Format_Indexed8); - const int buffer_size = 2048; - uint buf[buffer_size]; + uint buf[BufferSize]; uint *buffer = buf; const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; const uchar *srcData = src->data; uchar *destData = dest->data; - const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; - const StorePixelsFunc store = qStorePixels[destLayout->bpp]; - ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM; - ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM; - if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) { - // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method. - convertFromARGB32PM = destLayout->convertFromRGB32; + FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM; + ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM; + if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) { + // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method. + store = destLayout->storeFromRGB32; } else { // The drawhelpers do not mask the alpha value in RGB32, we want to here. if (src->format == QImage::Format_RGB32) - convertToARGB32PM = maskRGB32; + fetch = fetchRGB32ToARGB32PM; if (dest->format == QImage::Format_RGB32) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; + store = storeRGB32FromARGB32PM_sse4; else #endif - convertFromARGB32PM = convertRGB32FromARGB32PM; + store = storeRGB32FromARGB32PM; } } if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) && - destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) { + !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) { // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format. - convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM; + fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM; if (dest->format == QImage::Format_RGB32) - convertFromARGB32PM = maskRGB32; + store = storeRGB32FromARGB32; else - convertFromARGB32PM = destLayout->convertFromRGB32; + store = destLayout->storeFromRGB32; } QDitherInfo dither; QDitherInfo *ditherPtr = 0; @@ -196,12 +202,9 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio if (destLayout->bpp == QPixelLayout::BPP32) buffer = reinterpret_cast<uint *>(destData) + x; else - l = qMin(l, buffer_size); - const uint *ptr = fetch(buffer, srcData, x, l); - ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr); - ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr); - if (ptr != reinterpret_cast<uint *>(destData)) - store(destData, ptr, x, l); + l = qMin(l, BufferSize); + const uint *ptr = fetch(buffer, srcData, x, l, 0, ditherPtr); + store(destData, ptr, x, l, 0, ditherPtr); x += l; } srcData += src->bytes_per_line; @@ -217,39 +220,37 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im if (data->depth != qt_depthForFormat(dst_format)) return false; - const int buffer_size = 2048; - uint buffer[buffer_size]; + uint buf[BufferSize]; + uint *buffer = buf; const QPixelLayout *srcLayout = &qPixelLayouts[data->format]; const QPixelLayout *destLayout = &qPixelLayouts[dst_format]; uchar *srcData = data->data; - const FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; - const StorePixelsFunc store = qStorePixels[destLayout->bpp]; - ConvertFunc convertToARGB32PM = srcLayout->convertToARGB32PM; - ConvertFunc convertFromARGB32PM = destLayout->convertFromARGB32PM; - if (srcLayout->alphaWidth == 0 && destLayout->convertFromRGB32) { - // If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method. - convertFromARGB32PM = destLayout->convertFromRGB32; + FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM; + ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM; + if (!srcLayout->hasAlphaChannel && destLayout->storeFromRGB32) { + // If the source doesn't have an alpha channel, we can use the faster storeFromRGB32 method. + store = destLayout->storeFromRGB32; } else { if (data->format == QImage::Format_RGB32) - convertToARGB32PM = maskRGB32; + fetch = fetchRGB32ToARGB32PM; if (dst_format == QImage::Format_RGB32) { #ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) - convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; + store = storeRGB32FromARGB32PM_sse4; else #endif - convertFromARGB32PM = convertRGB32FromARGB32PM; + store = storeRGB32FromARGB32PM; } } if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) && - destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) { + !destLayout->hasAlphaChannel && destLayout->storeFromRGB32) { // 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; + fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM; + if (data->format == QImage::Format_RGB32) + store = storeRGB32FromARGB32; else - convertFromARGB32PM = destLayout->convertFromRGB32; + store = destLayout->storeFromRGB32; } QDitherInfo dither; QDitherInfo *ditherPtr = 0; @@ -261,13 +262,13 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im int x = 0; while (x < data->width) { dither.x = x; - int l = qMin(data->width - x, buffer_size); - const uint *ptr = fetch(buffer, srcData, x, l); - ptr = convertToARGB32PM(buffer, ptr, l, 0, ditherPtr); - ptr = convertFromARGB32PM(buffer, ptr, l, 0, ditherPtr); - // The conversions might be passthrough and not use the buffer, in that case we are already done. - if (srcData != (const uchar*)ptr) - store(srcData, ptr, x, l); + int l = data->width - x; + if (destLayout->bpp == QPixelLayout::BPP32) + buffer = reinterpret_cast<uint *>(srcData) + x; + else + l = qMin(l, BufferSize); + const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr); + store(srcData, ptr, x, l, nullptr, ditherPtr); x += l; } srcData += data->bytes_per_line; diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp index 0e2c2f492e..2f6649c1bc 100644 --- a/src/gui/image/qimage_sse4.cpp +++ b/src/gui/image/qimage_sse4.cpp @@ -47,12 +47,12 @@ QT_BEGIN_NAMESPACE -const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QVector<QRgb> *, QDitherInfo *) +void QT_FASTCALL storeRGB32FromARGB32PM_sse4(uchar *dest, const uint *src, int index, int count, + const QVector<QRgb> *, QDitherInfo *) { + uint *d = reinterpret_cast<uint *>(dest) + index; for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); - return buffer; + d[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); } void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 7086e102ea..6d358984d6 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -164,73 +164,13 @@ #include <private/qpnghandler_p.h> #endif +#include <private/qimagereaderwriterhelpers_p.h> + #include <algorithm> QT_BEGIN_NAMESPACE -#ifndef QT_NO_IMAGEFORMATPLUGIN -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats"))) -#endif - -enum _qt_BuiltInFormatType { -#ifndef QT_NO_IMAGEFORMAT_PNG - _qt_PngFormat, -#endif -#ifndef QT_NO_IMAGEFORMAT_BMP - _qt_BmpFormat, -#endif -#ifndef QT_NO_IMAGEFORMAT_PPM - _qt_PpmFormat, - _qt_PgmFormat, - _qt_PbmFormat, -#endif -#ifndef QT_NO_IMAGEFORMAT_XBM - _qt_XbmFormat, -#endif -#ifndef QT_NO_IMAGEFORMAT_XPM - _qt_XpmFormat, -#endif - _qt_NumFormats, - _qt_NoFormat = -1 -}; - -#if !defined(QT_NO_IMAGEFORMAT_PPM) -# define MAX_MT_SIZE 20 -#elif !defined(QT_NO_IMAGEFORMAT_XBM) || !defined(QT_NO_IMAGEFORMAT_XPM) -# define MAX_MT_SIZE 10 -#else -# define MAX_MT_SIZE 4 -#endif - -struct _qt_BuiltInFormatStruct -{ - char extension[4]; - char mimeType[MAX_MT_SIZE]; -}; - -#undef MAX_MT_SIZE - -static const _qt_BuiltInFormatStruct _qt_BuiltInFormats[] = { -#ifndef QT_NO_IMAGEFORMAT_PNG - {"png", "png"}, -#endif -#ifndef QT_NO_IMAGEFORMAT_BMP - {"bmp", "bmp"}, -#endif -#ifndef QT_NO_IMAGEFORMAT_PPM - {"ppm", "x-portable-pixmap"}, - {"pgm", "x-portable-graymap"}, - {"pbm", "x-portable-bitmap"}, -#endif -#ifndef QT_NO_IMAGEFORMAT_XBM - {"xbm", "x-xbitmap"}, -#endif -#ifndef QT_NO_IMAGEFORMAT_XPM - {"xpm", "x-xpixmap"}, -#endif -}; -Q_STATIC_ASSERT(_qt_NumFormats == sizeof _qt_BuiltInFormats / sizeof *_qt_BuiltInFormats); +using namespace QImageReaderWriterHelpers; static QImageIOHandler *createReadHandlerHelper(QIODevice *device, const QByteArray &format, @@ -251,7 +191,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, typedef QMultiMap<int, QString> PluginKeyMap; // check if we have plugins that support the image format - QFactoryLoader *l = loader(); + auto l = QImageReaderWriterHelpers::pluginLoader(); const PluginKeyMap keyMap = l->keyMap(); #ifdef QIMAGEREADER_DEBUG @@ -1565,16 +1505,6 @@ QByteArray QImageReader::imageFormat(QIODevice *device) return format; } -#ifndef QT_NO_IMAGEFORMATPLUGIN -void supportedImageHandlerFormats(QFactoryLoader *loader, - QImageIOPlugin::Capability cap, - QList<QByteArray> *result); - -void supportedImageHandlerMimeTypes(QFactoryLoader *loader, - QImageIOPlugin::Capability cap, - QList<QByteArray> *result); -#endif - /*! Returns the list of image formats supported by QImageReader. @@ -1605,18 +1535,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader, QList<QByteArray> QImageReader::supportedImageFormats() { - QList<QByteArray> formats; - formats.reserve(_qt_NumFormats); - for (int i = 0; i < _qt_NumFormats; ++i) - formats << _qt_BuiltInFormats[i].extension; - -#ifndef QT_NO_IMAGEFORMATPLUGIN - supportedImageHandlerFormats(loader(), QImageIOPlugin::CanRead, &formats); -#endif // QT_NO_IMAGEFORMATPLUGIN - - std::sort(formats.begin(), formats.end()); - formats.erase(std::unique(formats.begin(), formats.end()), formats.end()); - return formats; + return QImageReaderWriterHelpers::supportedImageFormats(QImageReaderWriterHelpers::CanRead); } /*! @@ -1630,18 +1549,24 @@ QList<QByteArray> QImageReader::supportedImageFormats() QList<QByteArray> QImageReader::supportedMimeTypes() { - QList<QByteArray> mimeTypes; - mimeTypes.reserve(_qt_NumFormats); - for (const auto &fmt : _qt_BuiltInFormats) - mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType); + return QImageReaderWriterHelpers::supportedMimeTypes(QImageReaderWriterHelpers::CanRead); +} -#ifndef QT_NO_IMAGEFORMATPLUGIN - supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanRead, &mimeTypes); -#endif // QT_NO_IMAGEFORMATPLUGIN +/*! + \since 5.12 - std::sort(mimeTypes.begin(), mimeTypes.end()); - mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end()); - return mimeTypes; + Returns the list of image formats corresponding to \a mimeType. + + Note that the QGuiApplication instance must be created before this function is + called. + + \sa supportedImageFormats(), supportedMimeTypes() +*/ + +QList<QByteArray> QImageReader::imageFormatsForMimeType(const QByteArray &mimeType) +{ + return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType, + QImageReaderWriterHelpers::CanRead); } QT_END_NAMESPACE diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h index 9d6c1e0b1e..4e9a08b6e6 100644 --- a/src/gui/image/qimagereader.h +++ b/src/gui/image/qimagereader.h @@ -144,6 +144,7 @@ public: static QByteArray imageFormat(QIODevice *device); static QList<QByteArray> supportedImageFormats(); static QList<QByteArray> supportedMimeTypes(); + static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType); private: Q_DISABLE_COPY(QImageReader) diff --git a/src/gui/image/qimagereaderwriterhelpers.cpp b/src/gui/image/qimagereaderwriterhelpers.cpp new file mode 100644 index 0000000000..a5b7fb6449 --- /dev/null +++ b/src/gui/image/qimagereaderwriterhelpers.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qimagereaderwriterhelpers_p.h" + +#include <qjsonarray.h> +#include <qmutex.h> +#include <private/qfactoryloader_p.h> + +QT_BEGIN_NAMESPACE + +namespace QImageReaderWriterHelpers { + +#ifndef QT_NO_IMAGEFORMATPLUGIN + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats"))) +Q_GLOBAL_STATIC(QMutex, loaderMutex) + +static void appendImagePluginFormats(QFactoryLoader *loader, + QImageIOPlugin::Capability cap, + QList<QByteArray> *result) +{ + typedef QMultiMap<int, QString> PluginKeyMap; + typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator; + + const PluginKeyMap keyMap = loader->keyMap(); + const PluginKeyMapConstIterator cend = keyMap.constEnd(); + int i = -1; + QImageIOPlugin *plugin = 0; + result->reserve(result->size() + keyMap.size()); + for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) { + if (it.key() != i) { + i = it.key(); + plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i)); + } + const QByteArray key = it.value().toLatin1(); + if (plugin && (plugin->capabilities(0, key) & cap) != 0) + result->append(key); + } +} + +static void appendImagePluginMimeTypes(QFactoryLoader *loader, + QImageIOPlugin::Capability cap, + QList<QByteArray> *result, + QList<QByteArray> *resultKeys = nullptr) +{ + QList<QJsonObject> metaDataList = loader->metaData(); + + const int pluginCount = metaDataList.size(); + for (int i = 0; i < pluginCount; ++i) { + const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject(); + const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray(); + const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray(); + QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i)); + const int keyCount = keys.size(); + for (int k = 0; k < keyCount; ++k) { + const QByteArray key = keys.at(k).toString().toLatin1(); + if (plugin && (plugin->capabilities(0, key) & cap) != 0) { + result->append(mimeTypes.at(k).toString().toLatin1()); + if (resultKeys) + resultKeys->append(key); + } + } + } +} + +QSharedPointer<QFactoryLoader> pluginLoader() +{ + loaderMutex()->lock(); + return QSharedPointer<QFactoryLoader>(loader(), [](QFactoryLoader *) { + loaderMutex()->unlock(); + }); +} + +static inline QImageIOPlugin::Capability pluginCapability(Capability cap) +{ + return cap == CanRead ? QImageIOPlugin::CanRead : QImageIOPlugin::CanWrite; +} + +#endif // QT_NO_IMAGEFORMATPLUGIN + +QList<QByteArray> supportedImageFormats(Capability cap) +{ + QList<QByteArray> formats; + formats.reserve(_qt_NumFormats); + for (int i = 0; i < _qt_NumFormats; ++i) + formats << _qt_BuiltInFormats[i].extension; + +#ifndef QT_NO_IMAGEFORMATPLUGIN + appendImagePluginFormats(loader(), pluginCapability(cap), &formats); +#endif // QT_NO_IMAGEFORMATPLUGIN + + std::sort(formats.begin(), formats.end()); + formats.erase(std::unique(formats.begin(), formats.end()), formats.end()); + return formats; +} + +QList<QByteArray> supportedMimeTypes(Capability cap) +{ + QList<QByteArray> mimeTypes; + mimeTypes.reserve(_qt_NumFormats); + for (const auto &fmt : _qt_BuiltInFormats) + mimeTypes.append(QByteArrayLiteral("image/") + fmt.mimeType); + +#ifndef QT_NO_IMAGEFORMATPLUGIN + appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes); +#endif // QT_NO_IMAGEFORMATPLUGIN + + std::sort(mimeTypes.begin(), mimeTypes.end()); + mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end()); + return mimeTypes; +} + +QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap) +{ + QList<QByteArray> formats; + if (mimeType.startsWith("image/")) { + const QByteArray type = mimeType.mid(sizeof("image/") - 1); + for (const auto &fmt : _qt_BuiltInFormats) { + if (fmt.mimeType == type && !formats.contains(fmt.extension)) + formats << fmt.extension; + } + } + +#ifndef QT_NO_IMAGEFORMATPLUGIN + QList<QByteArray> mimeTypes; + QList<QByteArray> keys; + appendImagePluginMimeTypes(loader(), pluginCapability(cap), &mimeTypes, &keys); + for (int i = 0; i < mimeTypes.size(); ++i) { + if (mimeTypes.at(i) == mimeType) { + const auto &key = keys.at(i); + if (!formats.contains(key)) + formats << key; + } + } +#endif // QT_NO_IMAGEFORMATPLUGIN + + return formats; +} + +} // QImageReaderWriterHelpers + +QT_END_NAMESPACE diff --git a/src/gui/image/qimagereaderwriterhelpers_p.h b/src/gui/image/qimagereaderwriterhelpers_p.h new file mode 100644 index 0000000000..6fe418a8ab --- /dev/null +++ b/src/gui/image/qimagereaderwriterhelpers_p.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QIMAGEREADERWRITERHELPERS_P_H +#define QIMAGEREADERWRITERHELPERS_P_H + +#include <QtGui/private/qtguiglobal_p.h> +#include <qsharedpointer.h> +#include "qimageiohandler.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_BEGIN_NAMESPACE + +class QFactoryLoader; + +namespace QImageReaderWriterHelpers { + +enum _qt_BuiltInFormatType { +#ifndef QT_NO_IMAGEFORMAT_PNG + _qt_PngFormat, +#endif +#ifndef QT_NO_IMAGEFORMAT_BMP + _qt_BmpFormat, +#endif +#ifndef QT_NO_IMAGEFORMAT_PPM + _qt_PpmFormat, + _qt_PgmFormat, + _qt_PbmFormat, +#endif +#ifndef QT_NO_IMAGEFORMAT_XBM + _qt_XbmFormat, +#endif +#ifndef QT_NO_IMAGEFORMAT_XPM + _qt_XpmFormat, +#endif + _qt_NumFormats, + _qt_NoFormat = -1 +}; + +#if !defined(QT_NO_IMAGEFORMAT_PPM) +# define MAX_MT_SIZE 20 +#elif !defined(QT_NO_IMAGEFORMAT_XBM) || !defined(QT_NO_IMAGEFORMAT_XPM) +# define MAX_MT_SIZE 10 +#else +# define MAX_MT_SIZE 4 +#endif + +struct _qt_BuiltInFormatStruct +{ + char extension[4]; + char mimeType[MAX_MT_SIZE]; +}; + +#undef MAX_MT_SIZE + +static const _qt_BuiltInFormatStruct _qt_BuiltInFormats[] = { +#ifndef QT_NO_IMAGEFORMAT_PNG + {"png", "png"}, +#endif +#ifndef QT_NO_IMAGEFORMAT_BMP + {"bmp", "bmp"}, +#endif +#ifndef QT_NO_IMAGEFORMAT_PPM + {"ppm", "x-portable-pixmap"}, + {"pgm", "x-portable-graymap"}, + {"pbm", "x-portable-bitmap"}, +#endif +#ifndef QT_NO_IMAGEFORMAT_XBM + {"xbm", "x-xbitmap"}, +#endif +#ifndef QT_NO_IMAGEFORMAT_XPM + {"xpm", "x-xpixmap"}, +#endif +}; +Q_STATIC_ASSERT(_qt_NumFormats == sizeof _qt_BuiltInFormats / sizeof *_qt_BuiltInFormats); + +#ifndef QT_NO_IMAGEFORMATPLUGIN +QSharedPointer<QFactoryLoader> pluginLoader(); +#endif + +enum Capability { + CanRead, + CanWrite +}; +QList<QByteArray> supportedImageFormats(Capability cap); +QList<QByteArray> supportedMimeTypes(Capability cap); +QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType, Capability cap); + +} + +QT_END_NAMESPACE + +#endif // QIMAGEREADERWRITERHELPERS_P_H diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index a39d204677..62eeb74727 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -102,7 +102,6 @@ #include <qfileinfo.h> #include <qimage.h> #include <qimageiohandler.h> -#include <qjsonarray.h> #include <qset.h> #include <qvariant.h> @@ -119,15 +118,12 @@ #include <private/qpnghandler_p.h> #endif +#include <private/qimagereaderwriterhelpers_p.h> + #include <algorithm> QT_BEGIN_NAMESPACE -#ifndef QT_NO_IMAGEFORMATPLUGIN -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QImageIOHandlerFactoryInterface_iid, QLatin1String("/imageformats"))) -#endif - static QImageIOHandler *createWriteHandlerHelper(QIODevice *device, const QByteArray &format) { @@ -139,7 +135,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device, typedef QMultiMap<int, QString> PluginKeyMap; // check if any plugins can write the image - QFactoryLoader *l = loader(); + auto l = QImageReaderWriterHelpers::pluginLoader(); const PluginKeyMap keyMap = l->keyMap(); int suffixPluginIndex = -1; #endif @@ -824,52 +820,6 @@ bool QImageWriter::supportsOption(QImageIOHandler::ImageOption option) const return d->handler->supportsOption(option); } - -#ifndef QT_NO_IMAGEFORMATPLUGIN -void supportedImageHandlerFormats(QFactoryLoader *loader, - QImageIOPlugin::Capability cap, - QList<QByteArray> *result) -{ - typedef QMultiMap<int, QString> PluginKeyMap; - typedef PluginKeyMap::const_iterator PluginKeyMapConstIterator; - - const PluginKeyMap keyMap = loader->keyMap(); - const PluginKeyMapConstIterator cend = keyMap.constEnd(); - int i = -1; - QImageIOPlugin *plugin = 0; - result->reserve(result->size() + keyMap.size()); - for (PluginKeyMapConstIterator it = keyMap.constBegin(); it != cend; ++it) { - if (it.key() != i) { - i = it.key(); - plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i)); - } - const QByteArray key = it.value().toLatin1(); - if (plugin && (plugin->capabilities(0, key) & cap) != 0) - result->append(key); - } -} - -void supportedImageHandlerMimeTypes(QFactoryLoader *loader, - QImageIOPlugin::Capability cap, - QList<QByteArray> *result) -{ - QList<QJsonObject> metaDataList = loader->metaData(); - - const int pluginCount = metaDataList.size(); - for (int i = 0; i < pluginCount; ++i) { - const QJsonObject metaData = metaDataList.at(i).value(QLatin1String("MetaData")).toObject(); - const QJsonArray keys = metaData.value(QLatin1String("Keys")).toArray(); - const QJsonArray mimeTypes = metaData.value(QLatin1String("MimeTypes")).toArray(); - QImageIOPlugin *plugin = qobject_cast<QImageIOPlugin *>(loader->instance(i)); - const int keyCount = keys.size(); - for (int k = 0; k < keyCount; ++k) { - if (plugin && (plugin->capabilities(0, keys.at(k).toString().toLatin1()) & cap) != 0) - result->append(mimeTypes.at(k).toString().toLatin1()); - } - } -} -#endif // QT_NO_IMAGEFORMATPLUGIN - /*! Returns the list of image formats supported by QImageWriter. @@ -897,30 +847,7 @@ void supportedImageHandlerMimeTypes(QFactoryLoader *loader, */ QList<QByteArray> QImageWriter::supportedImageFormats() { - QList<QByteArray> formats; -#ifndef QT_NO_IMAGEFORMAT_BMP - formats << "bmp"; -#endif -#ifndef QT_NO_IMAGEFORMAT_PPM - formats << "pbm" << "pgm" << "ppm"; -#endif -#ifndef QT_NO_IMAGEFORMAT_XBM - formats << "xbm"; -#endif -#ifndef QT_NO_IMAGEFORMAT_XPM - formats << "xpm"; -#endif -#ifndef QT_NO_IMAGEFORMAT_PNG - formats << "png"; -#endif - -#ifndef QT_NO_IMAGEFORMATPLUGIN - supportedImageHandlerFormats(loader(), QImageIOPlugin::CanWrite, &formats); -#endif // QT_NO_IMAGEFORMATPLUGIN - - std::sort(formats.begin(), formats.end()); - formats.erase(std::unique(formats.begin(), formats.end()), formats.end()); - return formats; + return QImageReaderWriterHelpers::supportedImageFormats(QImageReaderWriterHelpers::CanWrite); } /*! @@ -933,32 +860,24 @@ QList<QByteArray> QImageWriter::supportedImageFormats() */ QList<QByteArray> QImageWriter::supportedMimeTypes() { - QList<QByteArray> mimeTypes; -#ifndef QT_NO_IMAGEFORMAT_BMP - mimeTypes << "image/bmp"; -#endif -#ifndef QT_NO_IMAGEFORMAT_PPM - mimeTypes << "image/x-portable-bitmap"; - mimeTypes << "image/x-portable-graymap"; - mimeTypes << "image/x-portable-pixmap"; -#endif -#ifndef QT_NO_IMAGEFORMAT_XBM - mimeTypes << "image/x-xbitmap"; -#endif -#ifndef QT_NO_IMAGEFORMAT_XPM - mimeTypes << "image/x-xpixmap"; -#endif -#ifndef QT_NO_IMAGEFORMAT_PNG - mimeTypes << "image/png"; -#endif + return QImageReaderWriterHelpers::supportedMimeTypes(QImageReaderWriterHelpers::CanWrite); +} -#ifndef QT_NO_IMAGEFORMATPLUGIN - supportedImageHandlerMimeTypes(loader(), QImageIOPlugin::CanWrite, &mimeTypes); -#endif // QT_NO_IMAGEFORMATPLUGIN +/*! + \since 5.12 - std::sort(mimeTypes.begin(), mimeTypes.end()); - mimeTypes.erase(std::unique(mimeTypes.begin(), mimeTypes.end()), mimeTypes.end()); - return mimeTypes; + Returns the list of image formats corresponding to \a mimeType. + + Note that the QGuiApplication instance must be created before this function is + called. + + \sa supportedImageFormats(), supportedMimeTypes() +*/ + +QList<QByteArray> QImageWriter::imageFormatsForMimeType(const QByteArray &mimeType) +{ + return QImageReaderWriterHelpers::imageFormatsForMimeType(mimeType, + QImageReaderWriterHelpers::CanWrite); } QT_END_NAMESPACE diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h index fd1fdd07e8..29c06ccdd2 100644 --- a/src/gui/image/qimagewriter.h +++ b/src/gui/image/qimagewriter.h @@ -116,6 +116,7 @@ public: static QList<QByteArray> supportedImageFormats(); static QList<QByteArray> supportedMimeTypes(); + static QList<QByteArray> imageFormatsForMimeType(const QByteArray &mimeType); private: Q_DISABLE_COPY(QImageWriter) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 1ea503a268..4b2334ae52 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -248,9 +248,9 @@ QPixmap::QPixmap(const char * const xpm[]) QImage image(xpm); if (!image.isNull()) { if (data && data->pixelType() == QPlatformPixmap::BitmapType) - *this = QBitmap::fromImage(image); + *this = QBitmap::fromImage(std::move(image)); else - *this = fromImage(image); + *this = fromImage(std::move(image)); } } #endif @@ -691,7 +691,7 @@ QBitmap QPixmap::createHeuristicMask(bool clipTight) const QBitmap QPixmap::createMaskFromColor(const QColor &maskColor, Qt::MaskMode mode) const { QImage image = toImage().convertToFormat(QImage::Format_ARGB32); - return QBitmap::fromImage(image.createMaskFromColor(maskColor.rgba(), mode)); + return QBitmap::fromImage(std::move(image).createMaskFromColor(maskColor.rgba(), mode)); } /*! @@ -1018,9 +1018,9 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap) if (image.isNull()) { pixmap = QPixmap(); } else if (image.depth() == 1) { - pixmap = QBitmap::fromImage(image); + pixmap = QBitmap::fromImage(std::move(image)); } else { - pixmap = QPixmap::fromImage(image); + pixmap = QPixmap::fromImage(std::move(image)); } return stream; } diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 646e737afa..649a25250c 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -150,13 +150,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color) m_alpha = true; } - uint pixel = qPremultiply(color.rgba()); - const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()]; - Q_ASSERT(layout->convertFromARGB32PM); - layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0); - - //so premultiplied formats are supported and ARGB32 and RGB32 - blittable()->lock()->fill(pixel); + blittable()->lock()->fill(color); } } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 431002d032..13c1c29d5b 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -193,17 +193,12 @@ void QRasterPlatformPixmap::fill(const QColor &color) if (alpha != 255) { if (!image.hasAlphaChannel()) { QImage::Format toFormat = qt_alphaVersionForPainting(image.format()); - if (!image.isNull() && qt_depthForFormat(image.format()) == qt_depthForFormat(toFormat)) { - image.detach(); - image.d->format = toFormat; - } else { + if (!image.reinterpretAsFormat(toFormat)) image = QImage(image.width(), image.height(), toFormat); - } } } - pixel = qPremultiply(color.rgba()); - const QPixelLayout *layout = &qPixelLayouts[image.format()]; - layout->convertFromARGB32PM(&pixel, &pixel, 1, 0, 0); + image.fill(color); + return; } else if (image.format() == QImage::Format_Alpha8) { pixel = qAlpha(color.rgba()); } else if (image.format() == QImage::Format_Grayscale8) { diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 92f6964783..ea979db781 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -42,36 +42,73 @@ #include <qpa/qplatformpixmap.h> #include "qpixmap_raster_p.h" -#include <qglobal.h> +#include <qdebug.h> #include <QScopedArrayPointer> #include <qt_windows.h> +#include <algorithm> +#include <iterator> + QT_BEGIN_NAMESPACE -static inline void initBitMapInfoHeader(int width, int height, bool topToBottom, BITMAPINFOHEADER *bih) +template <typename Int> +static inline Int pad4(Int v) +{ + return (v + Int(3)) & ~Int(3); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const BITMAPINFOHEADER &bih) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "BITMAPINFOHEADER(" << bih.biWidth << 'x' << qAbs(bih.biHeight) + << (bih.biHeight < 0 ? ", top-down" : ", bottom-up") + << ", planes=" << bih.biPlanes << ", bitCount=" << bih.biBitCount + << ", compression=" << bih.biCompression << ", size=" + << bih.biSizeImage << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +static inline void initBitMapInfoHeader(int width, int height, bool topToBottom, + DWORD compression, DWORD bitCount, + BITMAPINFOHEADER *bih) { memset(bih, 0, sizeof(BITMAPINFOHEADER)); bih->biSize = sizeof(BITMAPINFOHEADER); bih->biWidth = width; bih->biHeight = topToBottom ? -height : height; bih->biPlanes = 1; - bih->biBitCount = 32; - bih->biCompression = BI_RGB; - bih->biSizeImage = width * height * 4; + bih->biBitCount = WORD(bitCount); + bih->biCompression = compression; + // scan lines are word-aligned (unless RLE) + const DWORD bytesPerLine = pad4(DWORD(width) * bitCount / 8); + bih->biSizeImage = bytesPerLine * DWORD(height); } -static inline void initBitMapInfo(int width, int height, bool topToBottom, BITMAPINFO *bmi) +enum { Indexed8ColorTableSize = 256 }; + +struct BITMAPINFO_COLORTABLE256 { // BITMAPINFO with 256 entry color table for Indexed 8 format + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[Indexed8ColorTableSize]; +}; + +template <class BITMAPINFO_T> // BITMAPINFO, BITMAPINFO_COLORTABLE256 +static inline void initBitMapInfo(int width, int height, bool topToBottom, + DWORD compression, DWORD bitCount, + BITMAPINFO_T *bmi) { - initBitMapInfoHeader(width, height, topToBottom, &bmi->bmiHeader); - memset(bmi->bmiColors, 0, sizeof(RGBQUAD)); + initBitMapInfoHeader(width, height, topToBottom, compression, bitCount, &bmi->bmiHeader); + memset(bmi->bmiColors, 0, sizeof(bmi->bmiColors)); } static inline uchar *getDiBits(HDC hdc, HBITMAP bitmap, int width, int height, bool topToBottom = true) { BITMAPINFO bmi; - initBitMapInfo(width, height, topToBottom, &bmi); + initBitMapInfo(width, height, topToBottom, BI_RGB, 32u, &bmi); uchar *result = new uchar[bmi.bmiHeader.biSizeImage]; - if (!GetDIBits(hdc, bitmap, 0, height, result, &bmi, DIB_RGB_COLORS)) { + if (!GetDIBits(hdc, bitmap, 0, UINT(height), result, &bmi, DIB_RGB_COLORS)) { delete [] result; qErrnoWarning("%s: GetDIBits() failed to get bitmap bits.", __FUNCTION__); return 0; @@ -98,18 +135,92 @@ static inline void copyImageDataCreateAlpha(const uchar *data, QImage *target) } } -static inline void copyImageData(const uchar *data, QImage *target) +// Flip RGB triplets from DIB to QImage formats. Scan lines are padded to 32bit +// both in QImage and DIB. +static inline void flipRgb3(uchar *p, int width, int height) { - const int height = target->height(); - const int bytesPerLine = target->bytesPerLine(); + const int lineSize = 3 * width; + const int linePad = pad4(lineSize) - lineSize; for (int y = 0; y < height; ++y) { - void *dest = static_cast<void *>(target->scanLine(y)); - const void *src = data + y * bytesPerLine; - memcpy(dest, src, bytesPerLine); + uchar *end = p + lineSize; + for ( ; p < end; p += 3) + std::swap(*p, *(p + 2)); + p += linePad; + } +} + +static inline RGBQUAD qRgbToRgbQuad(QRgb qrgb) +{ + RGBQUAD result = {BYTE(qBlue(qrgb)), BYTE(qGreen(qrgb)), BYTE(qRed(qrgb)), 0}; + return result; +} + +static inline QRgb rgbQuadToQRgb(RGBQUAD quad) +{ + return QRgb(quad.rgbBlue) + (QRgb(quad.rgbGreen) << 8) + (QRgb(quad.rgbRed) << 16) + + 0xff000000; +} + +// Helper for imageFromWinHBITMAP_*(), create image in desired format +static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *colorTableIn, + const void *data, QImage::Format format) +{ + const QSize size = QSize(header.biWidth, qAbs(header.biHeight)); + QImage image(size, format); + + int colorTableSize = 0; + switch (format) { + case QImage::Format_Mono: + colorTableSize = 2; + break; + case QImage::Format_Indexed8: + colorTableSize = Indexed8ColorTableSize; + break; + default: + break; + } + if (colorTableSize) { + Q_ASSERT(colorTableIn); + QVector<QRgb> colorTable; + colorTable.reserve(colorTableSize); + std::transform(colorTableIn, colorTableIn + colorTableSize, + std::back_inserter(colorTable), rgbQuadToQRgb); + image.setColorTable(colorTable); } + switch (header.biBitCount) { + case 32: + copyImageDataCreateAlpha(static_cast<const uchar *>(data), &image); + break; + case 1: + case 8: + case 16: + case 24: + Q_ASSERT(DWORD(image.byteCount()) == header.biSizeImage); + memcpy(image.bits(), data, header.biSizeImage); + if (format == QImage::Format_RGB888) + image = image.rgbSwapped(); + break; + default: + Q_UNREACHABLE(); + break; + } + return image; } +class DisplayHdc +{ + Q_DISABLE_COPY(DisplayHdc) +public: + DisplayHdc() : m_displayDc(GetDC(0)) {} + ~DisplayHdc() { ReleaseDC(0, m_displayDc); } + + operator HDC() const { return m_displayDc; } + +private: + const HDC m_displayDc; +}; + enum HBitmapFormat { HBitmapNoAlpha, @@ -131,34 +242,93 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap) return hbm; } -Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0) +static inline QImage::Format format32(int hbitmapFormat) { - if (p.isNull()) + switch (hbitmapFormat) { + case HBitmapNoAlpha: + return QImage::Format_RGB32; + case HBitmapAlpha: + return QImage::Format_ARGB32; + default: + break; + } + return QImage::Format_ARGB32_Premultiplied; +} + +Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat = 0) +{ + if (imageIn.isNull()) return 0; - HBITMAP bitmap = 0; - if (p.handle()->classId() != QPlatformPixmap::RasterClass) { - QRasterPlatformPixmap *data = new QRasterPlatformPixmap(p.depth() == 1 ? - QRasterPlatformPixmap::BitmapType : QRasterPlatformPixmap::PixmapType); - data->fromImage(p.toImage(), Qt::AutoColor); - return qt_pixmapToWinHBITMAP(QPixmap(data), hbitmapFormat); - } + // Define the header + DWORD compression = 0; + DWORD bitCount = 0; - QRasterPlatformPixmap *d = static_cast<QRasterPlatformPixmap*>(p.handle()); - const QImage *rasterImage = d->buffer(); - const int w = rasterImage->width(); - const int h = rasterImage->height(); + // Copy over the data + QImage image = imageIn; + switch (image.format()) { + case QImage::Format_Mono: + bitCount = 1u; + break; + case QImage::Format_RGB32: + case QImage::Format_ARGB32: + case QImage::Format_ARGB32_Premultiplied: { + compression = BI_RGB; + bitCount = 32u; + const QImage::Format targetFormat = format32(hbitmapFormat); + if (targetFormat != image.format()) + image = image.convertToFormat(targetFormat); + } + break; + case QImage::Format_RGB888: + compression = BI_RGB; + bitCount = 24u; + break; + case QImage::Format_Indexed8: + bitCount = 8u; + break; + case QImage::Format_RGB555: + bitCount = 16u; + break; + default: { + QImage::Format fallbackFormat = QImage::Format_ARGB32_Premultiplied; + switch (image.format()) { // Convert to a suitable format. + case QImage::Format_MonoLSB: + fallbackFormat = QImage::Format_Mono; + break; + case QImage::Format_RGB16: + fallbackFormat = QImage::Format_RGB555; + break; + case QImage::Format_Grayscale8: + fallbackFormat = QImage::Format_Indexed8; + break; + default: + break; + } // switch conversion format + return qt_imageToWinHBITMAP(imageIn.convertToFormat(fallbackFormat), hbitmapFormat); + } + } - HDC display_dc = GetDC(0); + const int w = image.width(); + const int h = image.height(); - // Define the header - BITMAPINFO bmi; - initBitMapInfo(w, h, true, &bmi); + BITMAPINFO_COLORTABLE256 bmiColorTable256; + initBitMapInfo(w, h, true, compression, bitCount, &bmiColorTable256); + BITMAPINFO &bmi = reinterpret_cast<BITMAPINFO &>(bmiColorTable256); + switch (image.format()) { + case QImage::Format_Mono: // Color table with 2 entries + case QImage::Format_Indexed8: + std::transform(image.colorTable().constBegin(), image.colorTable().constEnd(), + bmiColorTable256.bmiColors, qRgbToRgbQuad); + break; + default: + break; + } // Create the pixmap - uchar *pixels = 0; - bitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (void **) &pixels, 0, 0); - ReleaseDC(0, display_dc); + uchar *pixels = nullptr; + const HBITMAP bitmap = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, + reinterpret_cast<void **>(&pixels), 0, 0); if (!bitmap) { qErrnoWarning("%s, failed to create dibsection", __FUNCTION__); return 0; @@ -167,59 +337,121 @@ Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = qErrnoWarning("%s, did not allocate pixel data", __FUNCTION__); return 0; } - - // Copy over the data - QImage::Format imageFormat = QImage::Format_RGB32; - if (hbitmapFormat == HBitmapAlpha) - imageFormat = QImage::Format_ARGB32; - else if (hbitmapFormat == HBitmapPremultipliedAlpha) - imageFormat = QImage::Format_ARGB32_Premultiplied; - const QImage image = rasterImage->convertToFormat(imageFormat); - const int bytes_per_line = w * 4; - for (int y=0; y < h; ++y) - memcpy(pixels + y * bytes_per_line, image.scanLine(y), bytes_per_line); - + memcpy(pixels, image.constBits(), bmi.bmiHeader.biSizeImage); + if (image.format() == QImage::Format_RGB888) + flipRgb3(pixels, w, h); return bitmap; } +Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0) +{ + if (p.isNull()) + return 0; -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0) + QPlatformPixmap *platformPixmap = p.handle(); + if (platformPixmap->classId() != QPlatformPixmap::RasterClass) { + QRasterPlatformPixmap *data = new QRasterPlatformPixmap(p.depth() == 1 ? + QRasterPlatformPixmap::BitmapType : QRasterPlatformPixmap::PixmapType); + data->fromImage(p.toImage(), Qt::AutoColor); + return qt_pixmapToWinHBITMAP(QPixmap(data), hbitmapFormat); + } + + return qt_imageToWinHBITMAP(*static_cast<QRasterPlatformPixmap*>(platformPixmap)->buffer(), hbitmapFormat); +} + +static QImage::Format imageFromWinHBITMAP_Format(const BITMAPINFOHEADER &header, int hbitmapFormat) { - // Verify size - BITMAP bitmap_info; - memset(&bitmap_info, 0, sizeof(BITMAP)); + QImage::Format result = QImage::Format_Invalid; + switch (header.biBitCount) { + case 32: + result = hbitmapFormat == HBitmapNoAlpha + ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied; + break; + case 24: + result = QImage::Format_RGB888; + break; + case 16: + result = QImage::Format_RGB555; + break; + case 8: + result = QImage::Format_Indexed8; + break; + case 1: + result = QImage::Format_Mono; + break; + } + return result; +} - const int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info); - if (!res) { - qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info"); - return QPixmap(); +// Fast path for creating a QImage directly from a HBITMAP created by CreateDIBSection(), +// not requiring memory allocation. +static QImage imageFromWinHBITMAP_DibSection(HBITMAP bitmap, int hbitmapFormat) +{ + DIBSECTION dibSection; + memset(&dibSection, 0, sizeof(dibSection)); + dibSection.dsBmih.biSize = sizeof(dibSection.dsBmih); + + if (!GetObject(bitmap, sizeof(dibSection), &dibSection) + || !dibSection.dsBm.bmBits + || dibSection.dsBmih.biBitCount <= 8 // Cannot access the color table for Indexed8, Mono + || dibSection.dsBmih.biCompression != BI_RGB) { + return QImage(); } - const int w = bitmap_info.bmWidth; - const int h = bitmap_info.bmHeight; - - // Get bitmap bits - HDC display_dc = GetDC(0); - QScopedArrayPointer<uchar> data(getDiBits(display_dc, bitmap, w, h, true)); - if (data.isNull()) { - ReleaseDC(0, display_dc); - return QPixmap(); + + const QImage::Format imageFormat = imageFromWinHBITMAP_Format(dibSection.dsBmih, hbitmapFormat); + if (imageFormat == QImage::Format_Invalid) + return QImage(); + + return copyImageData(dibSection.dsBmih, nullptr, dibSection.dsBm.bmBits, imageFormat); +} + +// Create QImage from a HBITMAP using GetDIBits(), potentially with conversion. +static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int hbitmapFormat) +{ + BITMAPINFO_COLORTABLE256 bmiColorTable256; + BITMAPINFO &info = reinterpret_cast<BITMAPINFO &>(bmiColorTable256); + memset(&info, 0, sizeof(info)); + info.bmiHeader.biSize = sizeof(info.bmiHeader); + + DisplayHdc displayDc; + if (!GetDIBits(displayDc, bitmap, 0, 1, 0, &info, DIB_RGB_COLORS)) { + qErrnoWarning("%s: GetDIBits() failed to query data.", __FUNCTION__); + return QImage(); } - const QImage::Format imageFormat = hbitmapFormat == HBitmapNoAlpha ? - QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied; + if (info.bmiHeader.biHeight > 0) // Force top-down + info.bmiHeader.biHeight = -info.bmiHeader.biHeight; + info.bmiHeader.biCompression = BI_RGB; // Extract using no compression (can be BI_BITFIELD) + if (forceQuads) + info.bmiHeader.biBitCount = 32; - // Create image and copy data into image. - QImage image(w, h, imageFormat); - if (image.isNull()) { // failed to alloc? - ReleaseDC(0, display_dc); - qWarning("%s, failed create image of %dx%d", __FUNCTION__, w, h); - return QPixmap(); + const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat); + if (imageFormat == QImage::Format_Invalid) { + qWarning().nospace() << __FUNCTION__ << ": unsupported image format:" << info.bmiHeader; + return QImage(); } - copyImageDataCreateAlpha(data.data(), &image); - ReleaseDC(0, display_dc); - return QPixmap::fromImage(image); + + QScopedPointer<uchar> data(new uchar[info.bmiHeader.biSizeImage]); + if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) { + qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__); + return QImage(); + } + return copyImageData(info.bmiHeader, bmiColorTable256.bmiColors, data.data(), imageFormat); +} + +Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0) +{ + QImage result = imageFromWinHBITMAP_DibSection(bitmap, hbitmapFormat); + if (result.isNull()) + result = imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ false, hbitmapFormat); + return result; } +Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0) +{ + const QImage image = imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat); + return QPixmap::fromImage(image); +} Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p) { @@ -267,7 +499,7 @@ static QImage qt_imageFromWinIconHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h, true)); if (data.isNull()) return QImage(); - copyImageData(data.data(), &image); + memcpy(image.bits(), data.data(), image.byteCount()); return image; } @@ -303,7 +535,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) const int h = iconinfo.yHotspot * 2; BITMAPINFOHEADER bitmapInfo; - initBitMapInfoHeader(w, h, false, &bitmapInfo); + initBitMapInfoHeader(w, h, false, BI_RGB, 32u, &bitmapInfo); DWORD* bits; HBITMAP winBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0); diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 4b8b1203d6..3d1652f68b 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -86,7 +86,17 @@ QT_BEGIN_NAMESPACE \sa QCache, QPixmap */ -static int cache_limit = 10240; // 10 MB cache limit +static const int cache_limit_default = 10240; // 10 MB cache limit + +static inline int cost(const QPixmap &pixmap) +{ + // make sure to do a 64bit calculation + const qint64 costKb = static_cast<qint64>(pixmap.width()) * + pixmap.height() * pixmap.depth() / (8 * 1024); + const qint64 costMax = std::numeric_limits<int>::max(); + // a small pixmap should have at least a cost of 1(kb) + return static_cast<int>(qBound(1LL, costKb, costMax)); +} /*! \class QPixmapCache::Key @@ -237,7 +247,7 @@ uint qHash(const QPixmapCache::Key &k) QPMCache::QPMCache() : QObject(0), - QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit * 1024), + QCache<QPixmapCache::Key, QPixmapCacheEntry>(cache_limit_default), keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false) { } @@ -553,7 +563,7 @@ bool QPixmapCache::find(const Key &key, QPixmap* pixmap) bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) { - return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); + return pm_cache()->insert(key, pixmap, cost(pixmap)); } /*! @@ -573,7 +583,7 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap) */ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap) { - return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); + return pm_cache()->insert(pixmap, cost(pixmap)); } /*! @@ -590,7 +600,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap) //The key is not valid anymore, a flush happened before probably if (!key.d || !key.d->isValid) return false; - return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8); + return pm_cache()->replace(key, pixmap, cost(pixmap)); } /*! @@ -603,7 +613,7 @@ bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap) int QPixmapCache::cacheLimit() { - return cache_limit; + return pm_cache()->maxCost(); } /*! @@ -616,8 +626,7 @@ int QPixmapCache::cacheLimit() void QPixmapCache::setCacheLimit(int n) { - cache_limit = n; - pm_cache()->setMaxCost(1024 * cache_limit); + pm_cache()->setMaxCost(n); } /*! diff --git a/src/gui/image/qxbmhandler.cpp b/src/gui/image/qxbmhandler.cpp index 155a4f88b4..24d86e116d 100644 --- a/src/gui/image/qxbmhandler.cpp +++ b/src/gui/image/qxbmhandler.cpp @@ -241,7 +241,7 @@ static bool write_xbm_image(const QImage &sourceImage, QIODevice *device, const } } } -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC strcpy_s(p, sizeof(" };\n"), " };\n"); #else strcpy(p, " };\n"); diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index 9c54b9ada4..17272ffe69 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -741,10 +741,6 @@ static const struct XPMRGBData { { QRGB(139,139, 0), "yellow4" }, { QRGB(154,205, 50), "yellowgreen" } }; -#if defined(Q_CC_MSVC) && _MSC_VER < 1600 -inline bool operator<(const XPMRGBData &data1, const XPMRGBData &data2) -{ return qstrcmp(data1.name, data2.name) < 0; } -#endif inline bool operator<(const char *name, const XPMRGBData &data) { return qstrcmp(name, data.name) < 0; } |