diff options
-rw-r--r-- | src/corelib/global/qprocessordetection.h | 5 | ||||
-rw-r--r-- | src/gui/image/qimage.cpp | 8 | ||||
-rw-r--r-- | src/gui/image/qimage_conversions.cpp | 26 | ||||
-rw-r--r-- | src/gui/image/qimage_sse2.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 2 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 2 | ||||
-rw-r--r-- | src/gui/opengl/qopenglgradientcache.cpp | 10 | ||||
-rw-r--r-- | src/gui/painting/qcolor.cpp | 55 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 30 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 35 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 38 | ||||
-rw-r--r-- | src/gui/painting/qrgb.h | 43 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qglgradientcache.cpp | 10 |
13 files changed, 168 insertions, 98 deletions
diff --git a/src/corelib/global/qprocessordetection.h b/src/corelib/global/qprocessordetection.h index a5eff7c7ce..cf7ee1b7aa 100644 --- a/src/corelib/global/qprocessordetection.h +++ b/src/corelib/global/qprocessordetection.h @@ -331,8 +331,7 @@ the size of the register). On some architectures where a pointer could be smaller than the register, the macro is defined above. - Try our best to define it to a literal, so it can be used in the preprocessor, - but fall back to sizeof(void*) on practically every 32-bit build. + Falls back to QT_POINTER_SIZE if not set explicitly for the platform. */ #ifndef Q_PROCESSOR_WORDSIZE # ifdef __SIZEOF_POINTER__ @@ -341,7 +340,7 @@ # elif defined(_LP64) || defined(__LP64__) || defined(WIN64) || defined(_WIN64) # define Q_PROCESSOR_WORDSIZE 8 # else -# define Q_PROCESSOR_WORDSIZE sizeof(void*) +# define Q_PROCESSOR_WORDSIZE QT_POINTER_SIZE # endif #endif diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index f549a04dfb..48c262ae7a 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1719,7 +1719,7 @@ void QImage::fill(const QColor &color) if (d->depth == 32) { uint pixel = color.rgba(); if (d->format == QImage::Format_ARGB32_Premultiplied || d->format == QImage::Format_RGBA8888_Premultiplied) - pixel = PREMUL(pixel); + pixel = qPremultiply(pixel); fill((uint) pixel); } else if (d->format == QImage::Format_RGB16) { @@ -2204,17 +2204,17 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) case Format_RGB32: //make sure alpha is 255, we depend on it in qdrawhelper for cases // when image is set as a texture pattern on a qbrush - ((uint *)s)[x] = uint(255 << 24) | index_or_rgb; + ((uint *)s)[x] = 0xff000000 | index_or_rgb; return; case Format_ARGB32: case Format_ARGB32_Premultiplied: ((uint *)s)[x] = index_or_rgb; return; case Format_RGB16: - ((quint16 *)s)[x] = qConvertRgb32To16(INV_PREMUL(index_or_rgb)); + ((quint16 *)s)[x] = qConvertRgb32To16(qUnpremultiply(index_or_rgb)); return; case Format_RGBX8888: - ((uint *)s)[x] = ARGB2RGBA(index_or_rgb | 0xff000000); + ((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb); return; case Format_RGBA8888: case Format_RGBA8888_Premultiplied: diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 9b79f4ccc0..e856959d51 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -77,7 +77,7 @@ static const uchar bitflip[256] = { 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255 }; -const uchar *qt_get_bitflip_array() // called from QPixmap code +const uchar *qt_get_bitflip_array() { return bitflip; } @@ -187,7 +187,7 @@ static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = PREMUL(*src_data); + *dest_data = qPremultiply(*src_data); ++src_data; ++dest_data; } @@ -304,7 +304,7 @@ static void convert_ARGB_to_RGBA_PM(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const quint32 *end = src_data + src->width; while (src_data < end) { - *dest_data = ARGB2RGBA(PREMUL(*src_data)); + *dest_data = ARGB2RGBA(qPremultiply(*src_data)); ++src_data; ++dest_data; } @@ -376,7 +376,7 @@ static void convert_RGBA_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const quint32 *end = src_data + src->width; while (src_data < end) { - *dest_data = PREMUL(RGBA2ARGB(*src_data)); + *dest_data = qPremultiply(RGBA2ARGB(*src_data)); ++src_data; ++dest_data; } @@ -395,7 +395,7 @@ static bool convert_RGBA_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConversio for (int i = 0; i < data->height; ++i) { const QRgb *end = rgb_data + data->width; while (rgb_data < end) { - *rgb_data = PREMUL(RGBA2ARGB(*rgb_data)); + *rgb_data = qPremultiply(RGBA2ARGB(*rgb_data)); ++rgb_data; } rgb_data += pad; @@ -429,7 +429,7 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve data->colortable[i] = qRgb(i, i, i); } else { for (int i = 0; i < data->colortable.size(); ++i) - data->colortable[i] = PREMUL(data->colortable.at(i)); + data->colortable[i] = qPremultiply(data->colortable.at(i)); // Fill the rest of the table in case src_data > colortable.size() const int oldSize = data->colortable.size(); @@ -604,7 +604,7 @@ static void convert_ARGB_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = INV_PREMUL(*src_data); + *dest_data = qUnpremultiply(*src_data); ++src_data; ++dest_data; } @@ -628,7 +628,7 @@ static void convert_ARGB_PM_to_RGB(QImageData *dest, const QImageData *src, Qt:: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = 0xff000000 | INV_PREMUL(*src_data); + *dest_data = 0xff000000 | qUnpremultiply(*src_data); ++src_data; ++dest_data; } @@ -652,7 +652,7 @@ static void convert_ARGB_PM_to_RGBx(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = ARGB2RGBA(0xff000000 | INV_PREMUL(*src_data)); + *dest_data = ARGB2RGBA(0xff000000 | qUnpremultiply(*src_data)); ++src_data; ++dest_data; } @@ -676,7 +676,7 @@ static void convert_ARGB_PM_to_RGBA(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = ARGB2RGBA(INV_PREMUL(*src_data)); + *dest_data = ARGB2RGBA(qUnpremultiply(*src_data)); ++src_data; ++dest_data; } @@ -748,7 +748,7 @@ static void convert_RGBA_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = INV_PREMUL(RGBA2ARGB(*src_data)); + *dest_data = qUnpremultiply(RGBA2ARGB(*src_data)); ++src_data; ++dest_data; } @@ -772,7 +772,7 @@ static void convert_RGBA_PM_to_RGB(QImageData *dest, const QImageData *src, Qt:: for (int i = 0; i < src->height; ++i) { const QRgb *end = src_data + src->width; while (src_data < end) { - *dest_data = 0xff000000 | INV_PREMUL(RGBA2ARGB(*src_data)); + *dest_data = 0xff000000 | qUnpremultiply(RGBA2ARGB(*src_data)); ++src_data; ++dest_data; } @@ -862,7 +862,7 @@ static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format f } else if (format == QImage::Format_ARGB32_Premultiplied) { // check if the color table has alpha for (int i = 0; i < colorTable.size(); ++i) - colorTable[i] = PREMUL(colorTable.at(i)); + colorTable[i] = qPremultiply(colorTable.at(i)); } return colorTable; } diff --git a/src/gui/image/qimage_sse2.cpp b/src/gui/image/qimage_sse2.cpp index 0d6eac4ea2..037846c9aa 100644 --- a/src/gui/image/qimage_sse2.cpp +++ b/src/gui/image/qimage_sse2.cpp @@ -94,7 +94,7 @@ bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionF if (*p < 0x00ffffff) *p = 0; else if (*p < 0xff000000) - *p = PREMUL(*p); + *p = qPremultiply(*p); } d = reinterpret_cast<__m128i*>(p+pad); diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index 4c1b30a6d8..839a7a709f 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -148,7 +148,7 @@ void QBlittablePlatformPixmap::fill(const QColor &color) m_alpha = true; } - uint pixel = PREMUL(color.rgba()); + uint pixel = qPremultiply(color.rgba()); const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()]; Q_ASSERT(layout->convertFromARGB32PM); layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 37259adcd2..1465fea8b9 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -208,7 +208,7 @@ void QRasterPlatformPixmap::fill(const QColor &color) } } } - pixel = PREMUL(color.rgba()); + pixel = qPremultiply(color.rgba()); const QPixelLayout *layout = &qPixelLayouts[image.format()]; layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); } else { diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index 9c4fbbe013..9c312808a2 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -168,7 +168,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; - colorTable[pos++] = ARGB2RGBA(PREMUL(current_color)); + colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); while (fpos <= s.first().first) { colorTable[pos] = colorTable[pos - 1]; @@ -177,13 +177,13 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient } if (colorInterpolation) - current_color = PREMUL(current_color); + current_color = qPremultiply(current_color); for (int i = 0; i < s.size() - 1; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); if (colorInterpolation) - next_color = PREMUL(next_color); + next_color = qPremultiply(next_color); while (fpos < s[i+1].first && pos < size) { int dist = int(256 * ((fpos - s[i].first) * delta)); @@ -191,7 +191,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient if (colorInterpolation) colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); else - colorTable[pos] = ARGB2RGBA(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); ++pos; fpos += incr; } @@ -200,7 +200,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient Q_ASSERT(s.size() > 0); - uint last_color = ARGB2RGBA(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); for (;pos < size; ++pos) colorTable[pos] = last_color; diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 706273c151..b9d3ca888e 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -2499,6 +2499,41 @@ QDataStream &operator>>(QDataStream &stream, QColor &color) } #endif // QT_NO_DATASTREAM +// A table of precalculated results of 0x00ff00ff/alpha use by qUnpremultiply: +const uint qt_inv_premul_factor[256] = { + 0, 16711935, 8355967, 5570645, 4177983, 3342387, 2785322, 2387419, + 2088991, 1856881, 1671193, 1519266, 1392661, 1285533, 1193709, 1114129, + 1044495, 983055, 928440, 879575, 835596, 795806, 759633, 726605, + 696330, 668477, 642766, 618960, 596854, 576273, 557064, 539094, + 522247, 506422, 491527, 477483, 464220, 451673, 439787, 428511, + 417798, 407608, 397903, 388649, 379816, 371376, 363302, 355573, + 348165, 341059, 334238, 327685, 321383, 315319, 309480, 303853, + 298427, 293191, 288136, 283253, 278532, 273966, 269547, 265268, + 261123, 257106, 253211, 249431, 245763, 242201, 238741, 235379, + 232110, 228930, 225836, 222825, 219893, 217038, 214255, 211543, + 208899, 206320, 203804, 201348, 198951, 196611, 194324, 192091, + 189908, 187774, 185688, 183647, 181651, 179698, 177786, 175915, + 174082, 172287, 170529, 168807, 167119, 165464, 163842, 162251, + 160691, 159161, 157659, 156186, 154740, 153320, 151926, 150557, + 149213, 147893, 146595, 145321, 144068, 142837, 141626, 140436, + 139266, 138115, 136983, 135869, 134773, 133695, 132634, 131590, + 130561, 129549, 128553, 127572, 126605, 125653, 124715, 123792, + 122881, 121984, 121100, 120229, 119370, 118524, 117689, 116866, + 116055, 115254, 114465, 113686, 112918, 112160, 111412, 110675, + 109946, 109228, 108519, 107818, 107127, 106445, 105771, 105106, + 104449, 103800, 103160, 102527, 101902, 101284, 100674, 100071, + 99475, 98887, 98305, 97730, 97162, 96600, 96045, 95496, + 94954, 94417, 93887, 93362, 92844, 92331, 91823, 91322, + 90825, 90334, 89849, 89368, 88893, 88422, 87957, 87497, + 87041, 86590, 86143, 85702, 85264, 84832, 84403, 83979, + 83559, 83143, 82732, 82324, 81921, 81521, 81125, 80733, + 80345, 79961, 79580, 79203, 78829, 78459, 78093, 77729, + 77370, 77013, 76660, 76310, 75963, 75619, 75278, 74941, + 74606, 74275, 73946, 73620, 73297, 72977, 72660, 72346, + 72034, 71725, 71418, 71114, 70813, 70514, 70218, 69924, + 69633, 69344, 69057, 68773, 68491, 68211, 67934, 67659, + 67386, 67116, 66847, 66581, 66317, 66055, 65795, 65537 +}; /***************************************************************************** QColor global functions (documentation only) @@ -2581,6 +2616,26 @@ QDataStream &operator>>(QDataStream &stream, QColor &color) */ /*! + \fn QRgb qPremultiply(QRgb rgb) + \since 5.3 + \relates QColor + + Converts an unpremultiplied ARGB quadruplet \a rgb into a premultiplied ARGB quadruplet. + + \sa qUnpremultiply() +*/ + +/*! + \fn QRgb qUnpremultiply(QRgb rgb) + \since 5.3 + \relates QColor + + Converts a premultiplied ARGB quadruplet \a rgb into an unpremultiplied ARGB quadruplet. + + \sa qPremultiply() +*/ + +/*! \fn QColor QColor::convertTo(Spec colorSpec) const Creates a copy of \e this color in the format specified by \a colorSpec. diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 1851734bbc..52a6b5d211 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -255,7 +255,7 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint * Q_CONSTEXPR uchar blueRightShift = 8 - blueWidth<Format>(); for (int i = 0; i < count; ++i) { - const uint color = INV_PREMUL(src[i]); + const uint color = qUnpremultiply(src[i]); const uint red = ((color >> redRightShift) & redMask) << redShift<Format>(); const uint green = ((color >> greenRightShift) & greenMask) << greenShift<Format>(); const uint blue = ((color >> blueRightShift) & blueMask) << blueShift<Format>(); @@ -387,7 +387,7 @@ static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src, red = (red << redLeftShift) | (red >> redRightShift); green = (green << greenLeftShift) | (green >> greenRightShift); blue = (blue << blueLeftShift) | (blue >> blueRightShift); - buffer[i] = PREMUL((alpha << 24) | (red << 16) | (green << 8) | blue); + buffer[i] = qPremultiply((alpha << 24) | (red << 16) | (green << 8) | blue); } } return buffer; @@ -446,7 +446,7 @@ static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src if (!layout->premultiplied) { for (int i = 0; i < count; ++i) - buffer[i] = INV_PREMUL(src[i]); + buffer[i] = qUnpremultiply(src[i]); src = buffer; } for (int i = 0; i < count; ++i) { @@ -505,7 +505,7 @@ static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = qConvertRgb32To16(INV_PREMUL(src[i])); + buffer[i] = qConvertRgb32To16(qUnpremultiply(src[i])); return buffer; } #endif @@ -515,7 +515,7 @@ static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint const QPixelLayout *, const QRgb *clut) { for (int i = 0; i < count; ++i) - buffer[i] = PREMUL(clut[src[i]]); + buffer[i] = qPremultiply(clut[src[i]]); return buffer; } @@ -529,7 +529,7 @@ static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = PREMUL(src[i]); + buffer[i] = qPremultiply(src[i]); return buffer; } @@ -545,7 +545,7 @@ static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uin const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = PREMUL(RGBA2ARGB(src[i])); + buffer[i] = qPremultiply(RGBA2ARGB(src[i])); return buffer; } @@ -553,7 +553,7 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = INV_PREMUL(src[i]); + buffer[i] = qUnpremultiply(src[i]); return buffer; } @@ -569,7 +569,7 @@ static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const u const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(INV_PREMUL(src[i])); + buffer[i] = ARGB2RGBA(qUnpremultiply(src[i])); return buffer; } @@ -585,7 +585,7 @@ static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint const QPixelLayout *, const QRgb *) { for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(0xff000000 | INV_PREMUL(src[i])); + buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i])); return buffer; } @@ -853,9 +853,9 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = */ static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf) { - QRgb color_0 = PREMUL(rbuf->destColor0); - QRgb color_1 = PREMUL(rbuf->destColor1); - color = PREMUL(color); + QRgb color_0 = qPremultiply(rbuf->destColor0); + QRgb color_1 = qPremultiply(rbuf->destColor1); + color = qPremultiply(color); int r = qRed(color); int g = qGreen(color); @@ -6250,7 +6250,7 @@ static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer, quint32 color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); + qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer, @@ -6266,7 +6266,7 @@ static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer, quint32 color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(INV_PREMUL(color)), x, y, width, height, rasterBuffer->bytesPerLine()); + ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine()); } diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 0f98b07229..bbeb73f0af 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -599,14 +599,6 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { return (uint(t)) | (uint(t >> 24)); } -static Q_ALWAYS_INLINE uint PREMUL(uint x) { - uint a = x >> 24; - quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8; - t &= 0x000000ff00ff00ff; - return (uint(t)) | (uint(t >> 24)) | (a << 24); -} - #else // 32-bit versions static Q_ALWAYS_INLINE uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) { @@ -639,20 +631,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) { # pragma pop #endif -static Q_ALWAYS_INLINE uint PREMUL(uint x) { - uint a = x >> 24; - uint t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t &= 0xff00ff; - - x = ((x >> 8) & 0xff) * a; - x = (x + ((x >> 8) & 0xff) + 0x80); - x &= 0xff00; - x |= t | (a << 24); - return x; -} #endif + #if Q_BYTE_ORDER == Q_BIG_ENDIAN static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) { quint32 rgb = x >> 8; @@ -691,17 +672,9 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { return t; } -static Q_ALWAYS_INLINE uint INV_PREMUL(uint p) { - const uint alpha = qAlpha(p); - if (alpha == 255) - return p; - if (alpha == 0) - return 0; - // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256. - const uint invAlpha = 0x00ff00ffU / alpha; - // We add 0x8000 to get even rounding. The rounding also ensures that PREMUL(INV_PREMUL(p)) == p for all p. - return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha); -} +// FIXME: Remove when all Qt modules have stopped using PREMUL and INV_PREMUL +#define PREMUL(x) qPremultiply(x) +#define INV_PREMUL(p) qUnpremultiply(p) struct quint24 { quint24(uint value); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index bdd0d9cd4c..9a2e49618c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1823,7 +1823,7 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); if ((d->solid_color_filler.solid.color & 0xff000000) == 0 && s->composition_mode == QPainter::CompositionMode_SourceOver) { return; @@ -2272,7 +2272,7 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); break; default: - d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity)); break; } @@ -3662,7 +3662,7 @@ QImage QRasterBuffer::colorizeBitmap(const QImage &image, const QColor &color) QImage sourceImage = image.convertToFormat(QImage::Format_MonoLSB); QImage dest = QImage(sourceImage.size(), QImage::Format_ARGB32_Premultiplied); - QRgb fg = PREMUL(color.rgba()); + QRgb fg = qPremultiply(color.rgba()); QRgb bg = 0; int height = sourceImage.height(); @@ -3702,8 +3702,8 @@ QImage::Format QRasterBuffer::prepare(QImage *image) drawHelper = qDrawHelper + format; if (image->depth() == 1 && image->colorTable().size() == 2) { monoDestinationWithClut = true; - destColor0 = PREMUL(image->colorTable()[0]); - destColor1 = PREMUL(image->colorTable()[1]); + destColor0 = qPremultiply(image->colorTable()[0]); + destColor1 = qPremultiply(image->colorTable()[1]); } return format; @@ -4260,8 +4260,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } if (colorInterpolation) { - first_color = PREMUL(first_color); - second_color = PREMUL(second_color); + first_color = qPremultiply(first_color); + second_color = qPremultiply(second_color); } int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); @@ -4282,7 +4282,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (colorInterpolation) colorTable[i] = first_color; else - colorTable[i] = PREMUL(first_color); + colorTable[i] = qPremultiply(first_color); } if (i < second_index) { @@ -4311,7 +4311,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (colorInterpolation) colorTable[i] = color; else - colorTable[i] = PREMUL(color); + colorTable[i] = qPremultiply(color); } } @@ -4319,7 +4319,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (colorInterpolation) colorTable[i] = second_color; else - colorTable[i] = PREMUL(second_color); + colorTable[i] = qPremultiply(second_color); } return; @@ -4327,7 +4327,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); if (stopCount == 1) { - current_color = PREMUL(current_color); + current_color = qPremultiply(current_color); for (int i = 0; i < size; ++i) colorTable[i] = current_color; return; @@ -4344,7 +4344,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) // Up to first point - colorTable[pos++] = PREMUL(current_color); + colorTable[pos++] = qPremultiply(current_color); while (dpos <= begin_pos) { colorTable[pos] = colorTable[pos - 1]; ++pos; @@ -4366,8 +4366,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); if (colorInterpolation) { - current_color = PREMUL(current_color); - next_color = PREMUL(next_color); + current_color = qPremultiply(current_color); + next_color = qPremultiply(next_color); } qreal diff = stops[current_stop+1].first - stops[current_stop].first; @@ -4384,7 +4384,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (colorInterpolation) colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); else - colorTable[pos] = PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); ++pos; dpos += incr; @@ -4408,8 +4408,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (colorInterpolation) { if (skip != 1) - current_color = PREMUL(current_color); - next_color = PREMUL(next_color); + current_color = qPremultiply(current_color); + next_color = qPremultiply(next_color); } qreal diff = stops[current_stop+1].first - stops[current_stop].first; @@ -4421,7 +4421,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } // After last point - current_color = PREMUL(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); + current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); while (pos < size - 1) { colorTable[pos] = current_color; ++pos; @@ -4455,7 +4455,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = Solid; QColor c = qbrush_color(brush); QRgb rgba = c.rgba(); - solid.color = PREMUL(ARGB_COMBINE_ALPHA(rgba, alpha)); + solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha)); if ((solid.color & 0xff000000) == 0 && compositionMode == QPainter::CompositionMode_SourceOver) { type = None; diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h index 3c2bc5b97a..d8e19302d1 100644 --- a/src/gui/painting/qrgb.h +++ b/src/gui/painting/qrgb.h @@ -43,6 +43,7 @@ #define QRGB_H #include <QtCore/qglobal.h> +#include <QtCore/qprocessordetection.h> QT_BEGIN_NAMESPACE @@ -79,6 +80,48 @@ inline Q_DECL_CONSTEXPR int qGray(QRgb rgb) // convert RGB to gra inline Q_DECL_CONSTEXPR bool qIsGray(QRgb rgb) { return qRed(rgb) == qGreen(rgb) && qRed(rgb) == qBlue(rgb); } + +#if Q_PROCESSOR_WORDSIZE == 8 // 64-bit version +inline QRgb qPremultiply(QRgb x) +{ + const uint a = qAlpha(x); + quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8; + t &= 0x000000ff00ff00ff; + return (uint(t)) | (uint(t >> 24)) | (a << 24); +} +#else // 32-bit version +inline QRgb qPremultiply(QRgb x) +{ + const uint a = qAlpha(x); + uint t = (x & 0xff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; + + x = ((x >> 8) & 0xff) * a; + x = (x + ((x >> 8) & 0xff) + 0x80); + x &= 0xff00; + x |= t | (a << 24); + return x; +} +#endif + +Q_GUI_EXPORT extern const uint qt_inv_premul_factor[]; + +inline QRgb qUnpremultiply(QRgb p) +{ + const uint alpha = qAlpha(p); + // Alpha 255 and 0 are the two most common values, which makes them beneficial to short-cut. + if (alpha == 255) + return p; + if (alpha == 0) + return 0; + // (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256. + const uint invAlpha = qt_inv_premul_factor[alpha]; + // We add 0x8000 to get even rounding. The rounding also ensures that qPremultiply(qUnpremultiply(p)) == p for all p. + return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha); +} + QT_END_NAMESPACE #endif // QRGB_H diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index e0df4ccdf6..6160554472 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -184,7 +184,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; - colorTable[pos++] = qtToGlColor(PREMUL(current_color)); + colorTable[pos++] = qtToGlColor(qPremultiply(current_color)); while (fpos <= s.first().first) { colorTable[pos] = colorTable[pos - 1]; @@ -193,13 +193,13 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui } if (colorInterpolation) - current_color = PREMUL(current_color); + current_color = qPremultiply(current_color); for (int i = 0; i < s.size() - 1; ++i) { qreal delta = 1/(s[i+1].first - s[i].first); uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha); if (colorInterpolation) - next_color = PREMUL(next_color); + next_color = qPremultiply(next_color); while (fpos < s[i+1].first && pos < size) { int dist = int(256 * ((fpos - s[i].first) * delta)); @@ -207,7 +207,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui if (colorInterpolation) colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); else - colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + colorTable[pos] = qtToGlColor(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); ++pos; fpos += incr; } @@ -216,7 +216,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui Q_ASSERT(s.size() > 0); - uint last_color = qtToGlColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + uint last_color = qtToGlColor(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); for (;pos < size; ++pos) colorTable[pos] = last_color; |