diff options
34 files changed, 1042 insertions, 237 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 5cc1cf760f..224043ca79 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1766,11 +1766,11 @@ void QImage::fill(const QColor &color) break; case QImage::Format_BGR30: case QImage::Format_A2BGR30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderBGR>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64())); break; case QImage::Format_RGB30: case QImage::Format_A2RGB30_Premultiplied: - fill(qConvertArgb32ToA2rgb30<PixelOrderRGB>(color.rgba())); + fill(qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64())); break; case QImage::Format_RGB16: fill((uint) qConvertRgb32To16(color.rgba())); diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp index ab493fa85c..6622d4805f 100644 --- a/src/gui/opengl/qopenglgradientcache.cpp +++ b/src/gui/opengl/qopenglgradientcache.cpp @@ -34,8 +34,18 @@ #include "qopenglgradientcache_p.h" #include <private/qdrawhelper_p.h> #include <private/qopenglcontext_p.h> +#include <private/qrgba64_p.h> #include <QtCore/qmutex.h> -#include <QtGui/qopenglfunctions.h> +#include "qopenglfunctions.h" +#include "qopenglextensions_p.h" + +#ifndef GL_RGBA8 +#define GL_RGBA8 0x8058 +#endif + +#ifndef GL_RGBA16 +#define GL_RGBA16 0x805B +#endif QT_BEGIN_NAMESPACE @@ -137,33 +147,40 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient } CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode()); - uint buffer[1024]; + QRgba64 buffer[1024]; generateGradientColorTable(gradient, buffer, paletteSize(), opacity); funcs->glGenTextures(1, &cache_entry.texId); funcs->glBindTexture(GL_TEXTURE_2D, cache_entry.texId); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1, - 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + GLenum internalFormat = GL_RGBA16; + if (QOpenGLContext::currentContext()->isOpenGLES()) { + if (static_cast<QOpenGLExtensions*>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats)) + internalFormat = GL_RGBA8; + else + internalFormat = GL_RGBA; // Let OpenGLES use whatever it prefers. + } + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, paletteSize(), 1, + 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer); return cache.insert(hash_val, cache_entry).value().texId; } //TODO: Let GL generate the texture using an FBO -void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const +void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const { int pos = 0; QGradientStops s = gradient.stops(); - QVector<uint> colors(s.size()); + QVector<QRgba64> colors(s.size()); for (int i = 0; i < s.size(); ++i) - colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian) + colors[i] = s[i].second.rgba64(); bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); uint alpha = qRound(opacity * 256); - uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha); + QRgba64 current_color = combineAlpha256(colors[0], alpha); qreal incr = 1.0 / qreal(size); qreal fpos = 1.5 * incr; - colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color)); + colorTable[pos++] = qPremultiply(current_color); while (fpos <= s.first().first) { colorTable[pos] = colorTable[pos - 1]; @@ -176,7 +193,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient 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); + QRgba64 next_color = combineAlpha256(colors[i+1], alpha); if (colorInterpolation) next_color = qPremultiply(next_color); @@ -184,9 +201,9 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient int dist = int(256 * ((fpos - s[i].first) * delta)); int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); else - colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist))); + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); ++pos; fpos += incr; } @@ -195,7 +212,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient Q_ASSERT(s.size() > 0); - uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha))); + QRgba64 last_color = qPremultiply(combineAlpha256(colors[s.size() - 1], alpha)); for (;pos < size; ++pos) colorTable[pos] = last_color; diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h index bcdf3f4fcf..d368f4bcfc 100644 --- a/src/gui/opengl/qopenglgradientcache_p.h +++ b/src/gui/opengl/qopenglgradientcache_p.h @@ -50,6 +50,7 @@ #include <private/qopenglcontext_p.h> #include <QtCore/qmutex.h> #include <QGradient> +#include <qrgba64.h> QT_BEGIN_NAMESPACE @@ -83,7 +84,7 @@ public: private: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& gradient, - uint *colorTable, + QRgba64 *colorTable, int size, qreal opacity) const; GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity); void cleanCache(); diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 3010d4052a..fafc67cf46 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -44,6 +44,7 @@ HEADERS += \ painting/qregion.h \ painting/qrgb.h \ painting/qrgba64.h \ + painting/qrgba64_p.h \ painting/qstroker_p.h \ painting/qtextureglyphcache_p.h \ painting/qtransform.h \ diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp index 8fb5f4fd3f..61d57ca3f8 100644 --- a/src/gui/painting/qcosmeticstroker.cpp +++ b/src/gui/painting/qcosmeticstroker.cpp @@ -33,6 +33,7 @@ #include "qcosmeticstroker_p.h" #include "private/qpainterpath_p.h" +#include "private/qrgba64_p.h" #include <qdebug.h> QT_BEGIN_NAMESPACE @@ -280,7 +281,7 @@ void QCosmeticStroker::setup() drawCaps = state->lastPen.capStyle() != Qt::FlatCap; if (strokeSelection & FastDraw) { - color = INTERPOLATE_PIXEL_256(state->penData.solid.color, opacity, 0, 0); + color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32(); QRasterBuffer *buffer = state->penData.rasterBuffer; pixels = (uint *)buffer->buffer(); ppl = buffer->bytesPerLine()>>2; diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 57bb111538..b6f06135cd 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -51,6 +51,7 @@ #include <private/qdrawhelper_mips_dsp_p.h> #endif #include <private/qguiapplication_p.h> +#include <private/qrgba64_p.h> #include <qmath.h> QT_BEGIN_NAMESPACE @@ -758,6 +759,35 @@ static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, in return const_cast<uint *>(layout->convertToARGB32PM(buffer, ptr, length, layout, 0)); } +static QRgba64 *QT_FASTCALL destFetch64(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + uint buffer32[buffer_size]; + const uint *ptr = qFetchPixels[layout->bpp](buffer32, rasterBuffer->scanLine(y), x, length); + ptr = const_cast<uint *>(layout->convertToARGB32PM(buffer32, ptr, length, layout, 0)); + + for (int i = 0; i < length; ++i) { + buffer[i] = QRgba64::fromArgb32(ptr[i]); + } + return buffer; +} + +static QRgba64 *QT_FASTCALL destFetch64ARGB32(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x; + for (int i = 0; i < length; ++i) + buffer[i] = QRgba64::fromArgb32(src[i]).premultiplied(); + return buffer; +} + +template<QtPixelOrder PixelOrder> +static QRgba64 *QT_FASTCALL destFetch64RGB30(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) +{ + const uint *src = ((const uint *)rasterBuffer->scanLine(y)) + x; + for (int i = 0; i < length; ++i) + buffer[i] = qConvertA2rgb30ToRgb64<PixelOrder>(src[i]); + return buffer; +} static DestFetchProc destFetchProc[QImage::NImageFormats] = { @@ -788,6 +818,35 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] = destFetch, // Format_Grayscale8 }; +static DestFetchProc64 destFetchProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destFetch64, // Format_Mono, + destFetch64, // Format_MonoLSB + 0, // Format_Indexed8 + destFetch64, // Format_RGB32 + destFetch64ARGB32, // Format_ARGB32, + destFetch64, // Format_ARGB32_Premultiplied + destFetch64, // Format_RGB16 + destFetch64, // Format_ARGB8565_Premultiplied + destFetch64, // Format_RGB666 + destFetch64, // Format_ARGB6666_Premultiplied + destFetch64, // Format_RGB555 + destFetch64, // Format_ARGB8555_Premultiplied + destFetch64, // Format_RGB888 + destFetch64, // Format_RGB444 + destFetch64, // Format_ARGB4444_Premultiplied + destFetch64, // Format_RGBX8888 + destFetch64, // Format_RGBA8888 + destFetch64, // Format_RGBA8888_Premultiplied + destFetch64RGB30<PixelOrderBGR>, // Format_BGR30 + destFetch64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied + destFetch64RGB30<PixelOrderRGB>, // Format_RGB30 + destFetch64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied + destFetch64, // Format_Alpha8 + destFetch64, // Format_Grayscale8 +}; + /* Returns the color in the mono destination color table that is the "nearest" to /color/. @@ -904,6 +963,51 @@ static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, con } } +static void QT_FASTCALL convertFromRgb64(uint *dest, const QRgba64 *src, int length) +{ + for (int i = 0; i < length; ++i) { + dest[i] = src[i].toArgb32(); + } +} + +static void QT_FASTCALL destStore64(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint buf[buffer_size]; + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + StorePixelsFunc store = qStorePixels[layout->bpp]; + uchar *dest = rasterBuffer->scanLine(y); + while (length) { + int l = qMin(length, buffer_size); + const uint *ptr = 0; + convertFromRgb64(buf, buffer, l); + if (!layout->premultiplied && !layout->alphaWidth) + ptr = layout->convertFromRGB32(buf, buf, l, layout, 0); + else + ptr = layout->convertFromARGB32PM(buf, buf, l, layout, 0); + store(dest, ptr, x, l); + length -= l; + buffer += l; + x += l; + } +} + +static void QT_FASTCALL destStore64ARGB32(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint *dest = (uint*)rasterBuffer->scanLine(y) + x; + for (int i = 0; i < length; ++i) { + dest[i] = buffer[i].unpremultiplied().toArgb32(); + } +} + +template<QtPixelOrder PixelOrder> +static void QT_FASTCALL destStore64RGB30(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length) +{ + uint *dest = (uint*)rasterBuffer->scanLine(y) + x; + for (int i = 0; i < length; ++i) { + dest[i] = qConvertRgb64ToRgb30<PixelOrder>(buffer[i]); + } +} + static DestStoreProc destStoreProc[QImage::NImageFormats] = { 0, // Format_Invalid @@ -933,6 +1037,35 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = destStore, // Format_Grayscale8 }; +static DestStoreProc64 destStoreProc64[QImage::NImageFormats] = +{ + 0, // Format_Invalid + destStore64, // Format_Mono, + destStore64, // Format_MonoLSB + 0, // Format_Indexed8 + destStore64, // Format_RGB32 + destStore64ARGB32, // Format_ARGB32, + destStore64, // Format_ARGB32_Premultiplied + destStore64, // Format_RGB16 + destStore64, // Format_ARGB8565_Premultiplied + destStore64, // Format_RGB666 + destStore64, // Format_ARGB6666_Premultiplied + destStore64, // Format_RGB555 + destStore64, // Format_ARGB8555_Premultiplied + destStore64, // Format_RGB888 + destStore64, // Format_RGB444 + destStore64, // Format_ARGB4444_Premultiplied + destStore64, // Format_RGBX8888 + destStore64, // Format_RGBA8888 + destStore64, // Format_RGBA8888_Premultiplied + destStore64RGB30<PixelOrderBGR>, // Format_BGR30 + destStore64RGB30<PixelOrderBGR>, // Format_A2BGR30_Premultiplied + destStore64RGB30<PixelOrderRGB>, // Format_RGB30 + destStore64RGB30<PixelOrderRGB>, // Format_A2RGB30_Premultiplied + destStore64, // Format_Alpha8 + destStore64, // Format_Grayscale8 +}; + /* Source fetches @@ -2321,6 +2454,12 @@ static SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static const QRgba64& qt_gradient_pixel64_fixed(const QGradientData *data, int fixed_pos) +{ + int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -2405,6 +2544,75 @@ static const uint * QT_FASTCALL qt_fetch_linear_gradient(uint *buffer, const Ope return b; } +static const QRgba64 * QT_FASTCALL qt_fetch_linear_gradient_rgb64(QRgba64 *buffer, const Operator *op, const QSpanData *data, + int y, int x, int length) +{ + const QRgba64 *b = buffer; + qreal t, inc; + + bool affine = true; + qreal rx=0, ry=0; + if (op->linear.l == 0) { + t = inc = 0; + } else { + rx = data->m21 * (y + qreal(0.5)) + data->m11 * (x + qreal(0.5)) + data->dx; + ry = data->m22 * (y + qreal(0.5)) + data->m12 * (x + qreal(0.5)) + data->dy; + t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off; + inc = op->linear.dx * data->m11 + op->linear.dy * data->m12; + affine = !data->m13 && !data->m23; + + if (affine) { + t *= (GRADIENT_STOPTABLE_SIZE - 1); + inc *= (GRADIENT_STOPTABLE_SIZE - 1); + } + } + + const QRgba64 *end = buffer + length; + if (affine) { + if (inc > qreal(-1e-5) && inc < qreal(1e-5)) { + QRgba64 color = qt_gradient_pixel64_fixed(&data->gradient, int(t * FIXPT_SIZE)); + qt_memfill64((quint64*)buffer, color, length); + } else { + if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) && + t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) { + // we can use fixed point math + int t_fixed = int(t * FIXPT_SIZE); + int inc_fixed = int(inc * FIXPT_SIZE); + while (buffer < end) { + *buffer = qt_gradient_pixel64_fixed(&data->gradient, t_fixed); + t_fixed += inc_fixed; + ++buffer; + } + } else { + // we have to fall back to float math + while (buffer < end) { + *buffer = qt_gradient_pixel64(&data->gradient, t/GRADIENT_STOPTABLE_SIZE); + t += inc; + ++buffer; + } + } + } + } else { // fall back to float math here as well + qreal rw = data->m23 * (y + qreal(0.5)) + data->m13 * (x + qreal(0.5)) + data->m33; + while (buffer < end) { + qreal x = rx/rw; + qreal y = ry/rw; + t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off; + + *buffer = qt_gradient_pixel64(&data->gradient, t); + rx += data->m11; + ry += data->m12; + rw += data->m13; + if (!rw) { + rw += data->m13; + } + ++buffer; + } + } + + return b; +} + static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data) { v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; @@ -2560,11 +2768,35 @@ void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_ comp_func_Clear_impl(dest, length, const_alpha); } +void QT_FASTCALL comp_func_solid_Clear_rgb64(QRgba64 *dest, int length, QRgba64, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, 0, length); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha255(dest[i], ialpha); + } + } +} + void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha) { comp_func_Clear_impl(dest, length, const_alpha); } +void QT_FASTCALL comp_func_Clear_rgb64(QRgba64 *dest, const QRgba64 *, int length, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, 0, length); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = multiplyAlpha255(dest[i], ialpha); + } + } +} + /* result = s dest = s * ca + d * cia @@ -2584,6 +2816,19 @@ void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint } } +void QT_FASTCALL comp_func_solid_Source_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255) + qt_memfill64((quint64*)dest, color, length); + else { + int ialpha = 255 - const_alpha; + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + dest[i] = color + multiplyAlpha255(dest[i], ialpha); + } + } +} + void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) { if (const_alpha == 255) { @@ -2598,14 +2843,34 @@ void QT_FASTCALL comp_func_Source(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL } } +void QT_FASTCALL comp_func_Source_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) + ::memcpy(dest, src, length * sizeof(quint64)); + else { + int ialpha = 255 - const_alpha; + for (int i = 0; i < length; ++i) { + dest[i] = interpolate255(src[i], const_alpha, dest[i], ialpha); + } + } +} + void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) { } +void QT_FASTCALL comp_func_solid_Destination_rgb64(QRgba64 *, int, QRgba64, uint) +{ +} + void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint) { } +void QT_FASTCALL comp_func_Destination_rgb64(QRgba64 *, const QRgba64 *, int, uint) +{ +} + /* result = s + d * sia dest = (s + d * sia) * ca + d * cia @@ -2627,6 +2892,19 @@ void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, } } +void QT_FASTCALL comp_func_solid_SourceOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha == 255 && color.isOpaque()) { + qt_memfill64((quint64*)dest, color, length); + } else { + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + dest[i] = color + multiplyAlpha65535(dest[i], 65535 - color.alpha()); + } + } +} + void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) { PRELOAD_INIT2(dest, src) @@ -2648,6 +2926,24 @@ void QT_FASTCALL comp_func_SourceOver(uint *Q_DECL_RESTRICT dest, const uint *Q_ } } +void QT_FASTCALL comp_func_SourceOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 s = src[i]; + if (s.isOpaque()) + dest[i] = s; + else if (!s.isTransparent()) + dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + dest[i] = s + multiplyAlpha65535(dest[i], 65535 - s.alpha()); + } + } +} + /* result = d + s * dia dest = (d + s * dia) * ca + d * cia @@ -2665,6 +2961,16 @@ void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint co } } +void QT_FASTCALL comp_func_solid_DestinationOver_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha) +{ + if (const_alpha != 255) + color = multiplyAlpha255(color, const_alpha); + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = d + multiplyAlpha65535(color, 65535 - d.alpha()); + } +} + void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha) { PRELOAD_INIT2(dest, src) @@ -2684,6 +2990,22 @@ void QT_FASTCALL comp_func_DestinationOver(uint *Q_DECL_RESTRICT dest, const uin } } +void QT_FASTCALL comp_func_DestinationOver_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha) +{ + if (const_alpha == 255) { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + dest[i] = d + multiplyAlpha65535(src[i], 65535 - d.alpha()); + } + } else { + for (int i = 0; i < length; ++i) { + QRgba64 d = dest[i]; + QRgba64 s = multiplyAlpha255(src[i], const_alpha); + dest[i] = d + multiplyAlpha65535(s, 65535 - d.alpha()); + } + } +} + /* result = s * da dest = s * da * ca + d * cia @@ -4224,7 +4546,21 @@ static CompositionFunctionSolid functionForModeSolid_C[] = { rasterop_solid_NotDestination }; +static CompositionFunctionSolid64 functionForModeSolid64_C[] = { + comp_func_solid_SourceOver_rgb64, + comp_func_solid_DestinationOver_rgb64, + comp_func_solid_Clear_rgb64, + comp_func_solid_Source_rgb64, + comp_func_solid_Destination_rgb64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C; +static const CompositionFunctionSolid64 *functionForModeSolid64 = functionForModeSolid64_C; static CompositionFunction functionForMode_C[] = { comp_func_SourceOver, @@ -4267,7 +4603,21 @@ static CompositionFunction functionForMode_C[] = { rasterop_NotDestination }; +static CompositionFunction64 functionForMode64_C[] = { + comp_func_SourceOver_rgb64, + comp_func_DestinationOver_rgb64, + comp_func_Clear_rgb64, + comp_func_Source_rgb64, + comp_func_Destination_rgb64, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const CompositionFunction *functionForMode = functionForMode_C; +static const CompositionFunction64 *functionForMode64 = functionForMode64_C; static TextureBlendType getBlendType(const QSpanData *data) { @@ -4297,24 +4647,28 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in switch(data->type) { case QSpanData::Solid: - solidSource = (qAlpha(data->solid.color) == 255); + solidSource = data->solid.color.isOpaque(); break; case QSpanData::LinearGradient: solidSource = !data->gradient.alphaColor; getLinearGradientValues(&op.linear, data); - op.src_fetch = qt_fetch_linear_gradient; + op.srcFetch = qt_fetch_linear_gradient; + op.srcFetch64 = qt_fetch_linear_gradient_rgb64; break; case QSpanData::RadialGradient: solidSource = !data->gradient.alphaColor; getRadialGradientValues(&op.radial, data); - op.src_fetch = qt_fetch_radial_gradient; + op.srcFetch = qt_fetch_radial_gradient; + op.srcFetch64 = 0; //qt_fetch_radial_gradient_rgb64; break; case QSpanData::ConicalGradient: solidSource = !data->gradient.alphaColor; - op.src_fetch = qt_fetch_conical_gradient; + op.srcFetch = qt_fetch_conical_gradient; + op.srcFetch64 = 0; //qt_fetch_conical_gradient_rgb64; break; case QSpanData::Texture: - op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format]; + op.srcFetch = sourceFetch[getBlendType(data)][data->texture.format]; + op.srcFetch64 = 0; // sourceFetch64[getBlendType(data)][data->texture.format]; solidSource = !data->texture.hasAlpha; default: break; @@ -4324,12 +4678,13 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in if (op.mode == QPainter::CompositionMode_SourceOver && solidSource) op.mode = QPainter::CompositionMode_Source; - op.dest_fetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch = destFetchProc[data->rasterBuffer->format]; + op.destFetch64 = destFetchProc64[data->rasterBuffer->format]; if (op.mode == QPainter::CompositionMode_Source) { switch (data->rasterBuffer->format) { case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: - // don't clear dest_fetch as it sets up the pointer correctly to save one copy + // don't clear destFetch as it sets up the pointer correctly to save one copy break; default: { if (data->type == QSpanData::Texture && data->texture.const_alpha != 256) @@ -4343,16 +4698,21 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in } ++spans; } - if (!alphaSpans) - op.dest_fetch = 0; + if (!alphaSpans) { + op.destFetch = 0; + op.destFetch64 = 0; + } } } } - op.dest_store = destStoreProc[data->rasterBuffer->format]; + op.destStore = destStoreProc[data->rasterBuffer->format]; + op.destStore64 = destStoreProc64[data->rasterBuffer->format]; op.funcSolid = functionForModeSolid[op.mode]; + op.funcSolid64 = functionForModeSolid64[op.mode]; op.func = functionForMode[op.mode]; + op.func64 = functionForMode64[op.mode]; return op; } @@ -4369,16 +4729,17 @@ void blend_color_generic(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); uint buffer[buffer_size]; Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); while (count--) { int x = spans->x; int length = spans->len; while (length) { int l = qMin(buffer_size, length); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; - op.funcSolid(dest, l, data->solid.color, spans->coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.funcSolid(dest, l, color, spans->coverage); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); length -= l; x += l; } @@ -4391,15 +4752,16 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) QSpanData *data = reinterpret_cast<QSpanData *>(userData); Operator op = getOperator(data, spans, count); + const uint color = data->solid.color.toArgb32(); if (op.mode == QPainter::CompositionMode_Source) { // inline for performance while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { - QT_MEMFILL_UINT(target, spans->len, data->solid.color); + QT_MEMFILL_UINT(target, spans->len, color); } else { - uint c = BYTE_MUL(data->solid.color, spans->coverage); + uint c = BYTE_MUL(color, spans->coverage); int ialpha = 255 - spans->coverage; for (int i = 0; i < spans->len; ++i) target[i] = c + BYTE_MUL(target[i], ialpha); @@ -4411,7 +4773,35 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) while (count--) { uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; - op.funcSolid(target, spans->len, data->solid.color, spans->coverage); + op.funcSolid(target, spans->len, color, spans->coverage); + ++spans; + } +} + +void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + if (!op.funcSolid64) { + qDebug() << Q_FUNC_INFO << "unsupported 64bit blend attempted"; + return blend_color_generic(count, spans, userData); + } + + QRgba64 buffer[buffer_size]; + const QRgba64 color = data->solid.color; + + while (count--) { + int x = spans->x; + int length = spans->len; + while (length) { + int l = qMin(buffer_size, length); + QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.funcSolid64(dest, l, color, spans->coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); + length -= l; + x += l; + } ++spans; } } @@ -4426,13 +4816,12 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) from qt_gradient_quint16 with minimal overhead. */ QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode == QPainter::CompositionMode_SourceOver && - qAlpha(data->solid.color) == 255) + if (mode == QPainter::CompositionMode_SourceOver && data->solid.color.isOpaque()) mode = QPainter::CompositionMode_Source; if (mode == QPainter::CompositionMode_Source) { // inline for performance - ushort c = qConvertRgb32To16(data->solid.color); + ushort c = data->solid.color.toRgb16(); while (count--) { ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { @@ -4453,7 +4842,7 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData) if (mode == QPainter::CompositionMode_SourceOver) { while (count--) { - uint color = BYTE_MUL(data->solid.color, spans->coverage); + uint color = BYTE_MUL(data->solid.color.toArgb32(), spans->coverage); int ialpha = qAlpha(~color); ushort c = qConvertRgb32To16(color); ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; @@ -4517,7 +4906,7 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle int process_length = l; int process_x = x; - const uint *src = handler.fetch(process_x, y, process_length); + const typename T::BlendType *src = handler.fetch(process_x, y, process_length); int offset = 0; while (l > 0) { if (x == spans->x) // new span? @@ -4542,8 +4931,10 @@ void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handle } } +template<typename T> struct QBlendBase { + typedef T BlendType; QBlendBase(QSpanData *d, Operator o) : data(d) , op(o) @@ -4554,24 +4945,24 @@ struct QBlendBase QSpanData *data; Operator op; - uint *dest; + BlendType *dest; - uint buffer[buffer_size]; - uint src_buffer[buffer_size]; + BlendType buffer[buffer_size]; + BlendType src_buffer[buffer_size]; }; -class BlendSrcGeneric : public QBlendBase +class BlendSrcGeneric : public QBlendBase<uint> { public: BlendSrcGeneric(QSpanData *d, Operator o) - : QBlendBase(d, o) + : QBlendBase<uint>(d, o) { } const uint *fetch(int x, int y, int len) { - dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer; - return op.src_fetch(src_buffer, &op, data, y, x, len); + dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, y, len) : buffer; + return op.srcFetch(src_buffer, &op, data, y, x, len); } void process(int, int, int len, int coverage, const uint *src, int offset) @@ -4581,8 +4972,38 @@ public: void store(int x, int y, int len) { - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, y, dest, len); + if (op.destStore) + op.destStore(data->rasterBuffer, x, y, dest, len); + } +}; + +class BlendSrcGenericRGB64 : public QBlendBase<QRgba64> +{ +public: + BlendSrcGenericRGB64(QSpanData *d, Operator o) + : QBlendBase<QRgba64>(d, o) + { + } + + bool isSupported() const + { + return op.srcFetch64 && op.func64; + } + + const QRgba64 *fetch(int x, int y, int len) + { + dest = op.destFetch64(buffer, data->rasterBuffer, x, y, len); + return op.srcFetch64(src_buffer, &op, data, y, x, len); + } + + void process(int, int, int len, int coverage, const QRgba64 *src, int offset) + { + op.func64(dest + offset, src + offset, len, coverage); + } + + void store(int x, int y, int len) + { + op.destStore64(data->rasterBuffer, x, y, dest, len); } }; @@ -4593,6 +5014,20 @@ static void blend_src_generic(int count, const QSpan *spans, void *userData) handleSpans(count, spans, data, blend); } +static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + Operator op = getOperator(data, spans, count); + BlendSrcGenericRGB64 blend64(data, op); + if (blend64.isSupported()) + handleSpans(count, spans, data, blend64); + else { + qDebug("blend_src_generic_rgb64: unsupported 64-bit blend attempted"); + BlendSrcGeneric blend32(data, op); + handleSpans(count, spans, data, blend32); + } +} + static void blend_untransformed_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -4623,11 +5058,60 @@ static void blend_untransformed_generic(int count, const QSpan *spans, void *use const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; while (length) { int l = qMin(buffer_size, length); - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + } + } + } + ++spans; + } +} + +static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.srcFetch64 || !op.func64) { + qWarning() << Q_FUNC_INFO << "Unsupported blend"; + return blend_untransformed_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx); + int yoff = -qRound(-data->dy); + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = xoff + x; + int sy = yoff + spans->y; + if (sy >= 0 && sy < image_height && sx < image_width) { + if (sx < 0) { + x -= sx; + length += sx; + sx = 0; + } + if (sx + length > image_width) + length = image_width - sx; + if (length > 0) { + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + while (length) { + int l = qMin(buffer_size, length); + const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l); + QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.func64(dest, src, l, coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -4816,11 +5300,63 @@ static void blend_tiled_generic(int count, const QSpan *spans, void *userData) int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; - const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + const uint *src = op.srcFetch(src_buffer, &op, data, sy, sx, l); + uint *dest = op.destFetch ? op.destFetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; op.func(dest, src, l, coverage); - if (op.dest_store) - op.dest_store(data->rasterBuffer, x, spans->y, dest, l); + if (op.destStore) + op.destStore(data->rasterBuffer, x, spans->y, dest, l); + x += l; + sx += l; + length -= l; + if (sx >= image_width) + sx = 0; + } + ++spans; + } +} + +static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + Operator op = getOperator(data, spans, count); + if (!op.srcFetch64 || !op.func64) { + qDebug("unsupported rgb64 blend"); + return blend_tiled_generic(count, spans, userData); + } + QRgba64 buffer[buffer_size]; + QRgba64 src_buffer[buffer_size]; + + const int image_width = data->texture.width; + const int image_height = data->texture.height; + int xoff = -qRound(-data->dx) % image_width; + int yoff = -qRound(-data->dy) % image_height; + + if (xoff < 0) + xoff += image_width; + if (yoff < 0) + yoff += image_height; + + while (count--) { + int x = spans->x; + int length = spans->len; + int sx = (xoff + spans->x) % image_width; + int sy = (spans->y + yoff) % image_height; + if (sx < 0) + sx += image_width; + if (sy < 0) + sy += image_height; + + const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + const QRgba64 *src = op.srcFetch64(src_buffer, &op, data, sy, sx, l); + QRgba64 *dest = op.destFetch64 ? op.destFetch64(buffer, data->rasterBuffer, x, spans->y, l) : buffer; + op.func64(dest, src, l, coverage); + if (op.destStore64) + op.destStore64(data->rasterBuffer, x, spans->y, dest, l); x += l; sx += l; length -= l; @@ -5701,10 +6237,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_untransformed_generic, blend_untransformed_generic, blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, - blend_untransformed_generic, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, + blend_untransformed_generic_rgb64, blend_untransformed_generic, blend_untransformed_generic, }, @@ -5729,10 +6265,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_tiled_generic, blend_tiled_generic, blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, - blend_tiled_generic, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, + blend_tiled_generic_rgb64, blend_tiled_generic, blend_tiled_generic, }, @@ -5757,10 +6293,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5784,12 +6320,12 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic }, // Bilinear { @@ -5812,10 +6348,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, blend_src_generic, blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, - blend_src_generic, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, + blend_src_generic_rgb64, blend_src_generic, blend_src_generic, }, @@ -5840,10 +6376,10 @@ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats blend_src_generic, // RGBX8888 blend_src_generic, // RGBA8888 blend_src_generic, // RGBA8888_Premultiplied - blend_src_generic, // BGR30 - blend_src_generic, // A2BGR30_Premultiplied - blend_src_generic, // RGB30 - blend_src_generic, // A2RGB30_Premultiplied + blend_src_generic_rgb64, // BGR30 + blend_src_generic_rgb64, // A2BGR30_Premultiplied + blend_src_generic_rgb64, // RGB30 + blend_src_generic_rgb64, // A2RGB30_Premultiplied blend_src_generic, // Alpha8 blend_src_generic, // Grayscale8 } @@ -5999,13 +6535,11 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); - uint oldColor = data->solid.color; + QRgba64 oldColor = data->solid.color; while (count--) { int y = spans->y; - quint32 color = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); - - data->solid.color = color; + data->solid.color = QRgba64::fromArgb32(qt_gradient_pixel_fixed(&data->gradient, yinc * y + off)); blend_color_rgb16(1, spans, userData); ++spans; } @@ -6017,39 +6551,39 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) } inline static void qt_bitmapblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color, + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color), + qt_bitmapblit_template<quint32>(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride); } inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint16>(rasterBuffer, x, y, qConvertRgb32To16(color), + qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color.toRgb16(), map, mapWidth, mapHeight, mapStride); } static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = color.toRgb16(); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); @@ -6147,7 +6681,7 @@ static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, in } #endif -static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, +static void qt_alphamapblit_uint32(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *map, int mapWidth, int mapHeight, int mapStride, @@ -6243,28 +6777,38 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, } } + +static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, + int x, int y, const QRgba64 &color, + const uchar *map, + int mapWidth, int mapHeight, int mapStride, + const QClipData *clip) +{ + qt_alphamapblit_uint32(rasterBuffer, x, y, color.toArgb32(), map, mapWidth, mapHeight, mapStride, clip); +} + #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static void qt_alphamapblit_rgba8888(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *map, int mapWidth, int mapHeight, int mapStride, const QClipData *clip) { - qt_alphamapblit_argb32(rasterBuffer, x, y, ARGB2RGBA(color), map, mapWidth, mapHeight, mapStride, clip); + qt_alphamapblit_uint32(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), map, mapWidth, mapHeight, mapStride, clip); } #endif static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *src, int mapWidth, int mapHeight, int srcStride, const QClipData *clip) { - const quint32 c = color; + const quint32 c = color.toArgb32(); - int sr = qRed(color); - int sg = qGreen(color); - int sb = qBlue(color); - int sa = qAlpha(color); + int sr = qRed(c); + int sg = qGreen(c); + int sb = qBlue(c); + int sa = qAlpha(c); const QDrawHelperGammaTables *tables = QGuiApplicationPrivate::instance()->gammaTables(); if (!tables) @@ -6331,58 +6875,67 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, static void qt_rectfill_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - color, x, y, width, height, rasterBuffer->bytesPerLine()); + color.toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()), - qConvertRgb32To16(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.toRgb16(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_argb32(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - qUnpremultiply(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.unpremultiplied().toArgb32(), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(color), x, y, width, height, rasterBuffer->bytesPerLine()); + ARGB2RGBA(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_nonpremul_rgba(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) +{ + qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), + ARGB2RGBA(color.unpremultiplied().toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); +} + +template<QtPixelOrder PixelOrder> +static void qt_rectfill_rgb30(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + const QRgba64 &color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), - ARGB2RGBA(qUnpremultiply(color)), x, y, width, height, rasterBuffer->bytesPerLine()); + qConvertRgb64ToRgb30<PixelOrder>(color), x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_alpha(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qAlpha(color), x, y, width, height, rasterBuffer->bytesPerLine()); + color.alpha() >> 8, x, y, width, height, rasterBuffer->bytesPerLine()); } static void qt_rectfill_gray(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color) + const QRgba64 &color) { qt_rectfill<quint8>(reinterpret_cast<quint8 *>(rasterBuffer->buffer()), - qGray(color), x, y, width, height, rasterBuffer->bytesPerLine()); + qGray(color.toArgb32()), x, y, width, height, rasterBuffer->bytesPerLine()); } // Map table for destination image format. Contains function pointers @@ -6535,39 +7088,39 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = }, // Format_BGR30 { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderBGR> }, // Format_RGB30 { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied { - blend_color_generic, - blend_src_generic, + blend_color_generic_rgb64, + blend_src_generic_rgb64, 0, 0, 0, - 0 + qt_rectfill_rgb30<PixelOrderRGB> }, // Format_Alpha8 { @@ -6636,6 +7189,11 @@ inline void qt_memfill_template(quint16 *dest, quint16 value, int count) } #endif +void qt_memfill64(quint64 *dest, quint64 color, int count) +{ + qt_memfill_template<quint64>(dest, color, count); +} + #if !defined(__SSE2__) void qt_memfill16(quint16 *dest, quint16 color, int count) { diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 7e12e62151..36e2488a94 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -466,7 +466,7 @@ void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl, } void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *) @@ -475,8 +475,9 @@ void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); uchar *mask = const_cast<uchar *>(bitmap); + const uint c = color.toArgb32(); - pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, color, 0, mask, mapStride); + pixman_composite_over_n_8_0565_asm_neon(mapWidth, mapHeight, dest, destStride, c, 0, mask, mapStride); } extern "C" void blend_8_pixels_rgb16_on_rgb16_neon(quint16 *dst, const quint16 *src, int const_alpha); diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h index bd030a8bf3..37e060f147 100644 --- a/src/gui/painting/qdrawhelper_neon_p.h +++ b/src/gui/painting/qdrawhelper_neon_p.h @@ -82,7 +82,7 @@ void qt_blend_rgb16_on_rgb16_neon(uchar *destPixels, int dbpl, int const_alpha); void qt_alphamapblit_quint16_neon(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 480ba4c97b..501f1ce033 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -50,6 +50,7 @@ #include "QtGui/qcolor.h" #include "QtGui/qpainter.h" #include "QtGui/qimage.h" +#include "QtGui/qrgba64.h" #ifndef QT_FT_BEGIN_HEADER #define QT_FT_BEGIN_HEADER #define QT_FT_END_HEADER @@ -99,25 +100,25 @@ class QRasterPaintEngineState; typedef QT_FT_SpanFunc ProcessSpans; typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride); typedef void (*AlphamapBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uchar *bitmap, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*AlphaRGBBlitFunc)(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, const QRgba64 &color, const uint *rgbmask, int mapWidth, int mapHeight, int mapStride, const QClipData *clip); typedef void (*RectFillFunc)(QRasterBuffer *rasterBuffer, int x, int y, int width, int height, - quint32 color); + const QRgba64 &color); typedef void (*SrcOverBlendFunc)(uchar *destPixels, int dbpl, const uchar *src, int spbl, @@ -158,11 +159,14 @@ extern MemRotateFunc qMemRotateFunctions[QImage::NImageFormats][3]; extern DrawHelper qDrawHelper[QImage::NImageFormats]; void qBlendTexture(int count, const QSpan *spans, void *userData); +extern void qt_memfill64(quint64 *dest, quint64 value, int count); extern void qt_memfill32(quint32 *dest, quint32 value, int count); extern void qt_memfill16(quint16 *dest, quint16 value, int count); typedef void (QT_FASTCALL *CompositionFunction)(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunction64)(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha); typedef void (QT_FASTCALL *CompositionFunctionSolid)(uint *dest, int length, uint color, uint const_alpha); +typedef void (QT_FASTCALL *CompositionFunctionSolid64)(QRgba64 *dest, int length, QRgba64 color, uint const_alpha); struct LinearGradientValues { @@ -185,17 +189,27 @@ struct RadialGradientValues struct Operator; typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); +typedef QRgba64* (QT_FASTCALL *DestFetchProc64)(QRgba64 *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); +typedef void (QT_FASTCALL *DestStoreProc64)(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 *buffer, int length); typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); +typedef const QRgba64* (QT_FASTCALL *SourceFetchProc64)(QRgba64 *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); struct Operator { QPainter::CompositionMode mode; - DestFetchProc dest_fetch; - DestStoreProc dest_store; - SourceFetchProc src_fetch; + DestFetchProc destFetch; + DestStoreProc destStore; + SourceFetchProc srcFetch; CompositionFunctionSolid funcSolid; CompositionFunction func; + + DestFetchProc64 destFetch64; + DestStoreProc64 destStore64; + SourceFetchProc64 srcFetch64; + CompositionFunctionSolid64 funcSolid64; + CompositionFunction64 func64; + union { LinearGradientValues linear; RadialGradientValues radial; @@ -208,7 +222,7 @@ class QRasterPaintEngine; struct QSolidData { - uint color; + QRgba64 color; }; struct QLinearGradientData @@ -259,7 +273,7 @@ struct QGradientData #define GRADIENT_STOPTABLE_SIZE 1024 #define GRADIENT_STOPTABLE_SIZE_SHIFT 10 - uint* colorTable; //[GRADIENT_STOPTABLE_SIZE]; + QRgba64* colorTable; //[GRADIENT_STOPTABLE_SIZE]; uint alphaColor : 1; }; @@ -367,6 +381,12 @@ static inline uint qt_gradient_clamp(const QGradientData *data, int ipos) static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) { int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); + return data->colorTable[qt_gradient_clamp(data, ipos)].toArgb32(); +} + +static inline const QRgba64& qt_gradient_pixel64(const QGradientData *data, qreal pos) +{ + int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + qreal(0.5)); return data->colorTable[qt_gradient_clamp(data, ipos)]; } @@ -526,7 +546,7 @@ public: delta_det4_vec.v = Simd::v_add(delta_det4_vec.v, v_delta_delta_det16); \ b_vec.v = Simd::v_add(b_vec.v, v_delta_b4); \ for (int i = 0; i < 4; ++i) \ - *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]]; \ + *buffer++ = (extended_mask | v_buffer_mask.i[i]) & data->gradient.colorTable[index_vec.i[i]].toArgb32(); \ } #define FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP) \ @@ -644,7 +664,8 @@ static Q_ALWAYS_INLINE uint BYTE_MUL_RGB16_32(uint x, uint a) { return t; } -static Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; } +static Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_div_65535(uint x) { return (x + (x>>16) + 0x8000U) >> 16; } static Q_ALWAYS_INLINE uint BYTE_MUL_RGB30(uint x, uint a) { uint xa = x >> 30; @@ -687,6 +708,11 @@ inline quint24::operator uint() const template <class T> Q_STATIC_TEMPLATE_FUNCTION void qt_memfill(T *dest, T value, int count); +template<> inline void qt_memfill(quint64 *dest, quint64 color, int count) +{ + qt_memfill64(dest, color, count); +} + template<> inline void qt_memfill(quint32 *dest, quint32 color, int count) { qt_memfill32(dest, color, count); @@ -871,6 +897,64 @@ inline QRgb qConvertA2rgb30ToArgb32<PixelOrderRGB>(uint c) | ((c >> 2) & 0x000000ff); } +template<enum QtPixelOrder> inline QRgba64 qConvertA2rgb30ToRgb64(uint rgb); + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderBGR>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 blue = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 red = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<> +inline QRgba64 qConvertA2rgb30ToRgb64<PixelOrderRGB>(uint rgb) +{ + quint16 alpha = rgb >> 30; + quint16 red = (rgb >> 20) & 0x3ff; + quint16 green = (rgb >> 10) & 0x3ff; + quint16 blue = rgb & 0x3ff; + // Expand the range. + alpha |= (alpha << 2); + alpha |= (alpha << 4); + alpha |= (alpha << 8); + red = (red << 6) | (red >> 4); + green = (green << 6) | (green >> 4); + blue = (blue << 6) | (blue >> 4); + return qRgba64(red, green, blue, alpha); +} + +template<enum QtPixelOrder> inline unsigned int qConvertRgb64ToRgb30(QRgba64); + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderBGR>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (b << 20) | (g << 10) | r; +} + +template<> +inline unsigned int qConvertRgb64ToRgb30<PixelOrderRGB>(QRgba64 c) +{ + const uint a = c.alpha() >> 14; + const uint r = c.red() >> 6; + const uint g = c.green() >> 6; + const uint b = c.blue() >> 6; + return (a << 30) | (r << 20) | (g << 10) | b; +} + inline uint qRgbSwapRgb30(uint c) { const uint ag = c & 0xc00ffc00; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 84eb3b7909..b8957fe2fb 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -417,7 +417,7 @@ void qt_memfill16(quint16 *dest, quint16 value, int count) dest[count - 1] = value; } -void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, +void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) { @@ -468,18 +468,25 @@ void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, } } +void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, + const QRgba64 &color, + const uchar *src, int width, int height, int stride) +{ + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, color.toArgb32(), src, width, height, stride); +} + void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - qt_bitmapblit32_sse2(rasterBuffer, x, y, ARGB2RGBA(color), src, width, height, stride); + qt_bitmapblit32_sse2_base(rasterBuffer, x, y, ARGB2RGBA(color.toArgb32()), src, width, height, stride); } void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride) { - const quint16 c = qConvertRgb32To16(color); + const quint16 c = qConvertRgb32To16(color.toArgb32()); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 4d203c4f9d..50ee83aa2c 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -53,13 +53,13 @@ QT_BEGIN_NAMESPACE void qt_memfill32(quint32 *dest, quint32 value, int count); void qt_memfill16(quint16 *dest, quint16 value, int count); void qt_bitmapblit32_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit8888_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, - quint32 color, + const QRgba64 &color, const uchar *src, int width, int height, int stride); void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 18522cb6d0..3be6e0f1f4 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -57,6 +57,7 @@ #include <private/qstatictext_p.h> #include <private/qcosmeticstroker_p.h> #include "qmemrotate_p.h" +#include "qrgba64_p.h" #include "qpaintengine_raster_p.h" // #include "qbezier_p.h" @@ -830,7 +831,7 @@ void QRasterPaintEngine::updateRasterState() && s->intOpacity == 256 && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(s->penData.solid.color) == 255)); + && s->penData.solid.color.isOpaque())); } s->dirty = 0; @@ -1412,10 +1413,9 @@ static void fillRect_normalized(const QRect &r, QSpanData *data, if (data->fillRect && (mode == QPainter::CompositionMode_Source || (mode == QPainter::CompositionMode_SourceOver - && qAlpha(data->solid.color) == 255))) + && data->solid.color.isOpaque()))) { - data->fillRect(data->rasterBuffer, x1, y1, width, height, - data->solid.color); + data->fillRect(data->rasterBuffer, x1, y1, width, height, data->solid.color); return; } } @@ -1773,8 +1773,9 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color) Q_D(QRasterPaintEngine); QRasterPaintEngineState *s = state(); - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity)); - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(color.rgba64(), s->intOpacity)); + + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) { return; } @@ -2219,19 +2220,15 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe case QImage::Format_A2BGR30_Premultiplied: case QImage::Format_A2RGB30_Premultiplied: // Combine premultiplied color with the opacity set on the painter. - d->solid_color_filler.solid.color = - ((((color & 0x00ff00ff) * s->intOpacity) >> 8) & 0x00ff00ff) - | ((((color & 0xff00ff00) >> 8) * s->intOpacity) & 0xff00ff00); + d->solid_color_filler.solid.color = multiplyAlpha256(QRgba64::fromArgb32(color), s->intOpacity); break; default: - d->solid_color_filler.solid.color = qPremultiply(ARGB_COMBINE_ALPHA(color, s->intOpacity)); + d->solid_color_filler.solid.color = qPremultiply(combineAlpha256(QRgba64::fromArgb32(color), s->intOpacity)); break; } - if ((d->solid_color_filler.solid.color & 0xff000000) == 0 - && s->composition_mode == QPainter::CompositionMode_SourceOver) { + if (d->solid_color_filler.solid.color.isTransparent() && s->composition_mode == QPainter::CompositionMode_SourceOver) return; - } d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); @@ -4137,7 +4134,7 @@ class QGradientCache { inline CacheInfo(QGradientStops s, int op, QGradient::InterpolationMode mode) : stops(s), opacity(op), interpolationMode(mode) {} - uint buffer[GRADIENT_STOPTABLE_SIZE]; + QRgba64 buffer[GRADIENT_STOPTABLE_SIZE]; QGradientStops stops; int opacity; QGradient::InterpolationMode interpolationMode; @@ -4146,12 +4143,12 @@ class QGradientCache typedef QMultiHash<quint64, CacheInfo> QGradientColorTableHash; public: - inline const uint *getBuffer(const QGradient &gradient, int opacity) { + inline const QRgba64 *getBuffer(const QGradient &gradient, int opacity) { quint64 hash_val = 0; QGradientStops stops = gradient.stops(); for (int i = 0; i < stops.size() && i <= 2; i++) - hash_val += stops[i].second.rgba(); + hash_val += stops[i].second.rgba64(); QMutexLocker lock(&mutex); QGradientColorTableHash::const_iterator it = cache.constFind(hash_val); @@ -4174,9 +4171,9 @@ public: protected: inline int maxCacheSize() const { return 60; } inline void generateGradientColorTable(const QGradient& g, - uint *colorTable, + QRgba64 *colorTable, int size, int opacity) const; - uint *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { + QRgba64 *addCacheElement(quint64 hash_val, const QGradient &gradient, int opacity) { if (cache.size() == maxCacheSize()) { // may remove more than 1, but OK cache.erase(cache.begin() + (qrand() % maxCacheSize())); @@ -4190,7 +4187,7 @@ protected: QMutex mutex; }; -void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, int opacity) const +void QGradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, int opacity) const { QGradientStops stops = gradient.stops(); int stopCount = stops.count(); @@ -4199,14 +4196,16 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation); if (stopCount == 2) { - uint first_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); - uint second_color = ARGB_COMBINE_ALPHA(stops[1].second.rgba(), opacity); + QRgba64 first_color = combineAlpha256(stops[0].second.rgba64(), opacity); + QRgba64 second_color = combineAlpha256(stops[1].second.rgba64(), opacity); qreal first_stop = stops[0].first; qreal second_stop = stops[1].first; if (second_stop < first_stop) { - qSwap(first_color, second_color); + quint64 tmp = first_color; + first_color = second_color; + second_color = tmp; qSwap(first_stop, second_stop); } @@ -4218,15 +4217,15 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int first_index = qRound(first_stop * (GRADIENT_STOPTABLE_SIZE-1)); int second_index = qRound(second_stop * (GRADIENT_STOPTABLE_SIZE-1)); - uint red_first = qRed(first_color) << 16; - uint green_first = qGreen(first_color) << 16; - uint blue_first = qBlue(first_color) << 16; - uint alpha_first = qAlpha(first_color) << 16; + uint red_first = uint(first_color.red()) << 16; + uint green_first = uint(first_color.green()) << 16; + uint blue_first = uint(first_color.blue()) << 16; + uint alpha_first = uint(first_color.alpha()) << 16; - uint red_second = qRed(second_color) << 16; - uint green_second = qGreen(second_color) << 16; - uint blue_second = qBlue(second_color) << 16; - uint alpha_second = qAlpha(second_color) << 16; + uint red_second = uint(second_color.red()) << 16; + uint green_second = uint(second_color.green()) << 16; + uint blue_second = uint(second_color.blue()) << 16; + uint alpha_second = uint(second_color.alpha()) << 16; int i = 0; for (; i <= qMin(GRADIENT_STOPTABLE_SIZE, first_index); ++i) { @@ -4239,10 +4238,10 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (i < second_index) { qreal reciprocal = qreal(1) / (second_index - first_index); - int red_delta = qRound(int(red_second - red_first) * reciprocal); - int green_delta = qRound(int(green_second - green_first) * reciprocal); - int blue_delta = qRound(int(blue_second - blue_first) * reciprocal); - int alpha_delta = qRound(int(alpha_second - alpha_first) * reciprocal); + int red_delta = qRound((qreal(red_second) - red_first) * reciprocal); + int green_delta = qRound((qreal(green_second) - green_first) * reciprocal); + int blue_delta = qRound((qreal(blue_second) - blue_first) * reciprocal); + int alpha_delta = qRound((qreal(alpha_second) - alpha_first) * reciprocal); // rounding red_first += 1 << 15; @@ -4256,8 +4255,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint blue_first += blue_delta; alpha_first += alpha_delta; - const uint color = ((alpha_first << 8) & 0xff000000) | (red_first & 0xff0000) - | ((green_first >> 8) & 0xff00) | (blue_first >> 16); + const QRgba64 color = qRgba64(red_first >> 16, green_first >> 16, blue_first >> 16, alpha_first >> 16); if (colorInterpolation) colorTable[i] = color; @@ -4276,7 +4274,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint return; } - uint current_color = ARGB_COMBINE_ALPHA(stops[0].second.rgba(), opacity); + QRgba64 current_color = combineAlpha256(stops[0].second.rgba64(), opacity); if (stopCount == 1) { current_color = qPremultiply(current_color); for (int i = 0; i < size; ++i) @@ -4289,7 +4287,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint qreal end_pos = stops[stopCount-1].first; int pos = 0; // The position in the color table. - uint next_color; + QRgba64 next_color; qreal incr = 1 / qreal(size); // the double increment. qreal dpos = 1.5 * incr; // current position in gradient stop list (0 to 1) @@ -4313,8 +4311,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint ++current_stop; if (current_stop != 0) - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { current_color = qPremultiply(current_color); @@ -4333,9 +4331,9 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint int idist = 256 - dist; if (colorInterpolation) - colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist); + colorTable[pos] = interpolate256(current_color, idist, next_color, dist); else - colorTable[pos] = qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)); + colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist)); ++pos; dpos += incr; @@ -4354,8 +4352,8 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint if (skip == 1) current_color = next_color; else - current_color = ARGB_COMBINE_ALPHA(stops[current_stop].second.rgba(), opacity); - next_color = ARGB_COMBINE_ALPHA(stops[current_stop+1].second.rgba(), opacity); + current_color = combineAlpha256(stops[current_stop].second.rgba64(), opacity); + next_color = combineAlpha256(stops[current_stop+1].second.rgba64(), opacity); if (colorInterpolation) { if (skip != 1) @@ -4372,7 +4370,7 @@ void QGradientCache::generateGradientColorTable(const QGradient& gradient, uint } // After last point - current_color = qPremultiply(ARGB_COMBINE_ALPHA(stops[stopCount - 1].second.rgba(), opacity)); + current_color = qPremultiply(combineAlpha256(stops[stopCount - 1].second.rgba64(), opacity)); while (pos < size - 1) { colorTable[pos] = current_color; ++pos; @@ -4405,12 +4403,9 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode case Qt::SolidPattern: { type = Solid; QColor c = qbrush_color(brush); - QRgb rgba = c.rgba(); - solid.color = qPremultiply(ARGB_COMBINE_ALPHA(rgba, alpha)); - if ((solid.color & 0xff000000) == 0 - && compositionMode == QPainter::CompositionMode_SourceOver) { + solid.color = qPremultiply(combineAlpha256(c.rgba64(), alpha)); + if (solid.color.isTransparent() && compositionMode == QPainter::CompositionMode_SourceOver) type = None; - } break; } @@ -4419,7 +4414,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = LinearGradient; const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QLinearGradientData &linearData = gradient.linear; @@ -4436,7 +4431,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = RadialGradient; const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = g->spread(); QRadialGradientData &radialData = gradient.radial; @@ -4457,7 +4452,7 @@ void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode type = ConicalGradient; const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient()); gradient.alphaColor = !brush.isOpaque() || alpha != 256; - gradient.colorTable = const_cast<uint*>(qt_gradient_cache()->getBuffer(*g, alpha)); + gradient.colorTable = const_cast<QRgba64*>(qt_gradient_cache()->getBuffer(*g, alpha)); gradient.spread = QGradient::RepeatSpread; QConicalGradientData &conicalData = gradient.conical; diff --git a/src/gui/painting/qrgba64.h b/src/gui/painting/qrgba64.h index 2ea09e6bd6..51ce4ab10d 100644 --- a/src/gui/painting/qrgba64.h +++ b/src/gui/painting/qrgba64.h @@ -88,6 +88,9 @@ public: return fromRgba(rgb >> 16, rgb >> 8, rgb, rgb >> 24); } + Q_DECL_CONSTEXPR bool isOpaque() const { return c.alpha == 0xffff; } + Q_DECL_CONSTEXPR bool isTransparent() const { return c.alpha == 0; } + Q_DECL_CONSTEXPR quint16 red() const { return c.red; } Q_DECL_CONSTEXPR quint16 green() const { return c.green; } Q_DECL_CONSTEXPR quint16 blue() const { return c.blue; } @@ -133,6 +136,12 @@ public: return rgba; } + QRgba64 operator=(quint64 _rgba) + { + rgba = _rgba; + return *this; + } + private: static Q_DECL_CONSTEXPR uint div_257_floor(uint x) { return (x - (x >> 8)) >> 8; } static Q_DECL_CONSTEXPR uint div_257(uint x) { return div_257_floor(x + 128); } diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h new file mode 100644 index 0000000000..a1452af8d9 --- /dev/null +++ b/src/gui/painting/qrgba64_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QRGBA64_P_H +#define QRGBA64_P_H + +#include <QtGui/qrgba64.h> +#include <QtGui/private/qdrawhelper_p.h> + +QT_BEGIN_NAMESPACE + +inline QRgba64 combineAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64(rgba64.red(), rgba64.green(), rgba64.blue(), (rgba64.alpha() * alpha256) >> 8); +} + +inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256) +{ + return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8, + (rgba64.green() * alpha256) >> 8, + (rgba64.blue() * alpha256) >> 8, + (rgba64.alpha() * alpha256) >> 8); +} + +inline QRgba64 multiplyAlpha255(QRgba64 rgba64, uint alpha255) +{ + return QRgba64::fromRgba64(qt_div_255(rgba64.red() * alpha255), + qt_div_255(rgba64.green() * alpha255), + qt_div_255(rgba64.blue() * alpha255), + qt_div_255(rgba64.alpha() * alpha255)); +} + +inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535) +{ + return QRgba64::fromRgba64(qt_div_65535(rgba64.red() * alpha65535), + qt_div_65535(rgba64.green() * alpha65535), + qt_div_65535(rgba64.blue() * alpha65535), + qt_div_65535(rgba64.alpha() * alpha65535)); +} + +inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2)); +} + +inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2) +{ + return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2)); +} + +QT_END_NAMESPACE + +#endif // QRGBA64_P_H diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro index 7e9d438e1b..e90b516ef2 100644 --- a/tests/auto/gui/painting/qpainter/qpainter.pro +++ b/tests/auto/gui/painting/qpainter/qpainter.pro @@ -2,7 +2,7 @@ CONFIG += testcase CONFIG += parallel_test TARGET = tst_qpainter -QT += testlib +QT += testlib gui-private core-private qtHaveModule(widgets): QT += widgets widgets-private SOURCES += tst_qpainter.cpp diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 6582755aec..10b79fdd0f 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -53,6 +53,7 @@ #endif #include <qpixmap.h> +#include <private/qdrawhelper_p.h> #include <qpainter.h> #ifndef QT_NO_WIDGETS @@ -125,8 +126,12 @@ private slots: void fillRect3(); void fillRect4_data() { fillRect2_data(); } void fillRect4(); + void fillRectNonPremul_data(); void fillRectNonPremul(); + void fillRectRGB30_data(); + void fillRectRGB30(); + void drawEllipse_data(); void drawEllipse(); void drawClippedEllipse_data(); @@ -1245,22 +1250,87 @@ void tst_QPainter::fillRect4() QCOMPARE(image, expected); } +void tst_QPainter::fillRectNonPremul_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::addColumn<uint>("color"); + + QTest::newRow("argb32 7f1f3f7f") << QImage::Format_ARGB32 << qRgba(31, 63, 127, 127); + QTest::newRow("rgba8888 7f1f3f7f") << QImage::Format_RGBA8888 << qRgba(31, 63, 127, 127); + + QTest::newRow("argb32 3f1f3f7f") << QImage::Format_ARGB32 << qRgba(31, 63, 127, 63); + QTest::newRow("rgba8888 3f1f3f7f") << QImage::Format_RGBA8888 << qRgba(31, 63, 127, 63); + + QTest::newRow("argb32 070375f4") << QImage::Format_ARGB32 << qRgba(3, 117, 244, 7); + QTest::newRow("rgba8888 070375f4") << QImage::Format_RGBA8888 << qRgba(3, 117, 244, 7); + + QTest::newRow("argb32 0301fe0c") << QImage::Format_ARGB32 << qRgba(1, 254, 12, 3); + QTest::newRow("rgba8888 0301fe0c") << QImage::Format_RGBA8888 << qRgba(1, 254, 12, 3); + + QTest::newRow("argb32 01804010") << QImage::Format_ARGB32 << qRgba(128, 64, 32, 1); + QTest::newRow("rgba8888 01804010") << QImage::Format_RGBA8888 << qRgba(128, 64, 32, 1); +} + void tst_QPainter::fillRectNonPremul() { - QImage img1(1, 1, QImage::Format_ARGB32); - QImage img2(1, 1, QImage::Format_RGBA8888); + QFETCH(QImage::Format, format); + QFETCH(uint, color); - QPainter p1(&img1); - QPainter p2(&img2); + QImage image(1, 1, format); + QRectF rect(0, 0, 1, 1); + + // Fill with CompositionMode_SourceOver tests blend_color + image.fill(Qt::transparent); + QPainter painter(&image); + painter.fillRect(rect, QColor::fromRgba(color)); + painter.end(); + + // Fill with CompositionMode_Source tests rectfill. + painter.begin(&image); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, QColor::fromRgba(color)); + painter.end(); + + QRgb p = image.pixel(0, 0); + QCOMPARE(qAlpha(p), qAlpha(color)); + QVERIFY(qAbs(qRed(p)-qRed(color)) <= 1); + QVERIFY(qAbs(qGreen(p)-qGreen(color)) <= 1); + QVERIFY(qAbs(qBlue(p)-qBlue(color)) <= 1); +} + +void tst_QPainter::fillRectRGB30_data() +{ + QTest::addColumn<uint>("color"); + QTest::newRow("17|43|259") << (0xc0000000 | (17 << 20) | (43 << 10) | 259); + QTest::newRow("2|33|444") << (0xc0000000 | (2 << 20) | (33 << 10) | 444); + QTest::newRow("1000|1000|1000") << (0xc0000000 | (1000 << 20) | (1000 << 10) | 1000); +} + +void tst_QPainter::fillRectRGB30() +{ + QFETCH(uint, color); QRectF rect(0, 0, 1, 1); - p1.fillRect(rect, qRgba(31, 63, 127, 127)); - p2.fillRect(rect, qRgba(31, 63, 127, 127)); - p1.end(); - p2.end(); + // Fill with CompositionMode_SourceOver tests blend_color + QImage image1(1, 1, QImage::Format_A2BGR30_Premultiplied); + image1.fill(Qt::transparent); + QPainter painter(&image1); + painter.fillRect(rect, QColor::fromRgba64(qConvertA2rgb30ToRgb64<PixelOrderBGR>(color))); + painter.end(); - QCOMPARE(img1.pixel(0, 0), img2.pixel(0,0)); + uint pixel1 = ((const uint*)(image1.bits()))[0]; + QCOMPARE(pixel1, color); + + // Fill with CompositionMode_Source tests rectfill. + QImage image2(1, 1, QImage::Format_RGB30); + painter.begin(&image2); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, QColor::fromRgba64(qConvertA2rgb30ToRgb64<PixelOrderRGB>(color))); + painter.end(); + + uint pixel2 = ((const uint*)(image2.bits()))[0]; + QCOMPARE(pixel2, color); } void tst_QPainter::drawPath_data() @@ -2619,28 +2689,6 @@ void tst_QPainter::porterDuff_warning() QVERIFY(qInstallMessageHandler(old) == porterDuff_warningChecker); } -class quint24 -{ -public: - inline quint24(quint32 v) - { - data[0] = qBlue(v); - data[1] = qGreen(v); - data[2] = qRed(v); - } - - inline operator quint32 () - { - return qRgb(data[2], data[1], data[0]); - } - - inline bool operator==(const quint24 &v) const { - return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]); - } - - uchar data[3]; -}; - void tst_QPainter::drawhelper_blend_color() { QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied); @@ -4064,10 +4112,10 @@ void tst_QPainter::extendedBlendModes() QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(127, 0, 37, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(126, 128, 165, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(127, 0, 38, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(255, 0, 75, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(255, 0, 76, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3)); diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png |