diff options
author | Kim Motoyoshi Kalland <kim.kalland@nokia.com> | 2012-01-13 12:07:11 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-02-07 15:52:01 +0100 |
commit | ba1cf5dae397031730fb77321db1807937e81617 (patch) | |
tree | 491f6eeeeba37dcb5764c0348ae4704c1e41c1e2 /src/gui | |
parent | fe2344bd44e183b9893934d175c61a725af29b90 (diff) |
Removed image format specific template functions in raster engine.
Simplified the raster engine by treating image formats in a more
generic way and removed some unused code.
Change-Id: Ib3979a1a6e3e6f17c5002248545779ec36fff7c9
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/image/qimage.cpp | 511 | ||||
-rw-r--r-- | src/gui/image/qpixmap_blitter.cpp | 26 | ||||
-rw-r--r-- | src/gui/image/qpixmap_raster.cpp | 42 | ||||
-rw-r--r-- | src/gui/painting/qblendfunctions.cpp | 208 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 3828 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_neon.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_p.h | 1361 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_sse2.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qdrawhelper_sse_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qmemrotate.cpp | 380 | ||||
-rw-r--r-- | src/gui/painting/qmemrotate_p.h | 38 |
11 files changed, 1830 insertions, 4570 deletions
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 07af19d06a..5b23dbf4dc 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -74,30 +74,6 @@ static inline bool isLocked(QImageData *data) return data != 0 && data->is_locked; } -static inline bool checkPixelSize(const QImage::Format format) -{ - switch (format) { - case QImage::Format_ARGB8565_Premultiplied: - return (sizeof(qargb8565) == 3); - case QImage::Format_RGB666: - return (sizeof(qrgb666) == 3); - case QImage::Format_ARGB6666_Premultiplied: - return (sizeof(qargb6666) == 3); - case QImage::Format_RGB555: - return (sizeof(qrgb555) == 2); - case QImage::Format_ARGB8555_Premultiplied: - return (sizeof(qargb8555) == 3); - case QImage::Format_RGB888: - return (sizeof(qrgb888) == 3); - case QImage::Format_RGB444: - return (sizeof(qrgb444) == 2); - case QImage::Format_ARGB4444_Premultiplied: - return (sizeof(qargb4444) == 2); - default: - return true; - } -} - #if defined(Q_CC_DEC) && defined(__alpha) && (__DECCXX_VER-0 >= 50190001) #pragma message disable narrowptr #endif @@ -141,12 +117,6 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid) return 0; // invalid parameter(s) - if (!checkPixelSize(format)) { - qWarning("QImageData::create(): Invalid pixel size for format %i", - format); - return 0; - } - uint width = size.width(); uint height = size.height(); uint depth = qt_depthForFormat(format); @@ -793,12 +763,6 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm if (format == QImage::Format_Invalid) return d; - if (!checkPixelSize(format)) { - qWarning("QImageData::create(): Invalid pixel size for format %i", - format); - return 0; - } - const int depth = qt_depthForFormat(format); const int calc_bytes_per_line = ((width * depth + 31)/32) * 4; const int min_bytes_per_line = (width * depth + 7)/8; @@ -1708,9 +1672,8 @@ void QImage::fill(const QColor &color) pixel = PREMUL(pixel); fill((uint) pixel); - } else if (d->depth == 16 && d->format == QImage::Format_RGB16) { - qrgb565 p(color.rgba()); - fill((uint) p.rawValue()); + } else if (d->format == QImage::Format_RGB16) { + fill((uint) qConvertRgb32To16(color.rgba())); } else if (d->depth == 1) { if (color == Qt::color1) @@ -2025,12 +1988,12 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers quint16 colorTableRGB16[256]; if (data->colortable.isEmpty()) { for (int i = 0; i < 256; ++i) - colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(qRgb(i, i, i), 0); + colorTableRGB16[i] = qConvertRgb32To16(qRgb(i, i, i)); } else { // 1) convert the existing colors to RGB16 const int tableSize = data->colortable.size(); for (int i = 0; i < tableSize; ++i) - colorTableRGB16[i] = qt_colorConvert<quint16, quint32>(data->colortable.at(i), 0); + colorTableRGB16[i] = qConvertRgb32To16(data->colortable.at(i)); data->colortable = QVector<QRgb>(); // 2) fill the rest of the table in case src_data > colortable.size() @@ -2068,7 +2031,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl quint16 *dst_data = (quint16 *) data->data; for (int i = 0; i < data->height; ++i) { - qt_memconvert(dst_data, src_data, data->width); + for (int j = 0; j < data->width; ++j) + dst_data[j] = qConvertRgb32To16(src_data[j]); src_data = (quint32 *) (((char*)src_data) + src_bytes_per_line); dst_data = (quint16 *) (((char*)dst_data) + dst_bytes_per_line); } @@ -2878,60 +2842,33 @@ static void convert_Mono_to_Indexed8(QImageData *dest, const QImageData *src, Qt } } -#define CONVERT_DECL(DST, SRC) \ - static void convert_##SRC##_to_##DST(QImageData *dest, \ - const QImageData *src, \ - Qt::ImageConversionFlags) \ - { \ - qt_rectconvert<DST, SRC>(reinterpret_cast<DST*>(dest->data), \ - reinterpret_cast<const SRC*>(src->data), \ - 0, 0, src->width, src->height, \ - dest->bytes_per_line, src->bytes_per_line); \ +// Cannot be used with indexed formats. +static void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + const int buffer_size = 2048; + uint buffer[buffer_size]; + const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; + const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; + const uchar *srcData = src->data; + uchar *destData = dest->data; + + FetchPixelsFunc fetch = qFetchPixels[srcLayout->bpp]; + StorePixelsFunc store = qStorePixels[destLayout->bpp]; + + for (int y = 0; y < src->height; ++y) { + int x = 0; + while (x < src->width) { + int l = qMin(src->width - x, buffer_size); + const uint *ptr = fetch(buffer, srcData, x, l); + ptr = srcLayout->convertToARGB32PM(buffer, ptr, l, srcLayout, 0); + ptr = destLayout->convertFromARGB32PM(buffer, ptr, l, destLayout, 0); + store(destData, ptr, x, l); + x += l; + } + srcData += src->bytes_per_line; + destData += dest->bytes_per_line; } - -CONVERT_DECL(quint32, quint16) -CONVERT_DECL(quint16, quint32) -CONVERT_DECL(quint32, qargb8565) -CONVERT_DECL(qargb8565, quint32) -CONVERT_DECL(quint32, qrgb555) -CONVERT_DECL(qrgb666, quint32) -CONVERT_DECL(quint32, qrgb666) -CONVERT_DECL(qargb6666, quint32) -CONVERT_DECL(quint32, qargb6666) -CONVERT_DECL(qrgb555, quint32) -#if (defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16)) -CONVERT_DECL(quint16, qrgb555) -CONVERT_DECL(qrgb555, quint16) -#endif -CONVERT_DECL(quint32, qrgb888) -CONVERT_DECL(qrgb888, quint32) -CONVERT_DECL(quint32, qargb8555) -CONVERT_DECL(qargb8555, quint32) -CONVERT_DECL(quint32, qrgb444) -CONVERT_DECL(qrgb444, quint32) -CONVERT_DECL(quint32, qargb4444) -CONVERT_DECL(qargb4444, quint32) -#undef CONVERT_DECL -#define CONVERT_PTR(DST, SRC) convert_##SRC##_to_##DST - -/* - Format_Invalid, - Format_Mono, - Format_MonoLSB, - Format_Indexed8, - Format_RGB32, - Format_ARGB32, - Format_ARGB32_Premultiplied, - Format_RGB16, - Format_ARGB8565_Premultiplied, - Format_RGB666, - Format_ARGB6666_Premultiplied, - Format_RGB555, - Format_ARGB8555_Premultiplied, - Format_RGB888 - Format_RGB444 - Format_ARGB4444_Premultiplied -*/ +} // first index source, second dest @@ -3005,15 +2942,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, mask_alpha_converter, mask_alpha_converter, - CONVERT_PTR(quint16, quint32), - CONVERT_PTR(qargb8565, quint32), - CONVERT_PTR(qrgb666, quint32), - CONVERT_PTR(qargb6666, quint32), - CONVERT_PTR(qrgb555, quint32), - CONVERT_PTR(qargb8555, quint32), - CONVERT_PTR(qrgb888, quint32), - CONVERT_PTR(qrgb444, quint32), - CONVERT_PTR(qargb4444, quint32) + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic }, // Format_RGB32 { @@ -3024,15 +2961,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat mask_alpha_converter, 0, convert_ARGB_to_ARGB_PM, - CONVERT_PTR(quint16, quint32), - CONVERT_PTR(qargb8565, quint32), - CONVERT_PTR(qrgb666, quint32), - CONVERT_PTR(qargb6666, quint32), - CONVERT_PTR(qrgb555, quint32), - CONVERT_PTR(qargb8555, quint32), - CONVERT_PTR(qrgb888, quint32), - CONVERT_PTR(qrgb444, quint32), - CONVERT_PTR(qargb4444, quint32) + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic, + convert_generic }, // Format_ARGB32 { @@ -3059,15 +2996,15 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, quint16), - CONVERT_PTR(quint32, quint16), - CONVERT_PTR(quint32, quint16), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, 0, #if defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16) - CONVERT_PTR(qrgb555, quint16), + convert_generic, #else 0, #endif @@ -3082,9 +3019,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb8565), - CONVERT_PTR(quint32, qargb8565), - CONVERT_PTR(quint32, qargb8565), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3101,9 +3038,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb666), - CONVERT_PTR(quint32, qrgb666), - CONVERT_PTR(quint32, qrgb666), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3120,9 +3057,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb6666), - CONVERT_PTR(quint32, qargb6666), - CONVERT_PTR(quint32, qargb6666), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3139,11 +3076,11 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb555), - CONVERT_PTR(quint32, qrgb555), - CONVERT_PTR(quint32, qrgb555), + convert_generic, + convert_generic, + convert_generic, #if defined(QT_QWS_DEPTH_15) && defined(QT_QWS_DEPTH_16) - CONVERT_PTR(quint16, qrgb555), + convert_generic, #else 0, #endif @@ -3162,9 +3099,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb8555), - CONVERT_PTR(quint32, qargb8555), - CONVERT_PTR(quint32, qargb8555), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3181,9 +3118,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb888), - CONVERT_PTR(quint32, qrgb888), - CONVERT_PTR(quint32, qrgb888), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3200,9 +3137,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qrgb444), - CONVERT_PTR(quint32, qrgb444), - CONVERT_PTR(quint32, qrgb444), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3219,9 +3156,9 @@ static Image_Converter converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - CONVERT_PTR(quint32, qargb4444), - CONVERT_PTR(quint32, qargb4444), - CONVERT_PTR(quint32, qargb4444), + convert_generic, + convert_generic, + convert_generic, 0, 0, 0, @@ -3626,35 +3563,28 @@ QRgb QImage::pixel(int x, int y) const qWarning("QImage::pixel: coordinate (%d,%d) out of range", x, y); return 12345; } - const uchar * s = scanLine(y); + + const uchar * s = constScanLine(y); switch(d->format) { case Format_Mono: - return d->colortable.at((*(s + (x >> 3)) >> (7- (x & 7))) & 1); + return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1); case Format_MonoLSB: return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1); case Format_Indexed8: return d->colortable.at((int)s[x]); - case Format_ARGB8565_Premultiplied: - return qt_colorConvert<quint32, qargb8565>(reinterpret_cast<const qargb8565*>(s)[x], 0); - case Format_RGB666: - return qt_colorConvert<quint32, qrgb666>(reinterpret_cast<const qrgb666*>(s)[x], 0); - case Format_ARGB6666_Premultiplied: - return qt_colorConvert<quint32, qargb6666>(reinterpret_cast<const qargb6666*>(s)[x], 0); - case Format_RGB555: - return qt_colorConvert<quint32, qrgb555>(reinterpret_cast<const qrgb555*>(s)[x], 0); - case Format_ARGB8555_Premultiplied: - return qt_colorConvert<quint32, qargb8555>(reinterpret_cast<const qargb8555*>(s)[x], 0); - case Format_RGB888: - return qt_colorConvert<quint32, qrgb888>(reinterpret_cast<const qrgb888*>(s)[x], 0); - case Format_RGB444: - return qt_colorConvert<quint32, qrgb444>(reinterpret_cast<const qrgb444*>(s)[x], 0); - case Format_ARGB4444_Premultiplied: - return qt_colorConvert<quint32, qargb4444>(reinterpret_cast<const qargb4444*>(s)[x], 0); + case Format_RGB32: + case Format_ARGB32: // Keep old behaviour. + case Format_ARGB32_Premultiplied: + return reinterpret_cast<const QRgb *>(s)[x]; case Format_RGB16: - return qt_colorConvert<quint32, quint16>(reinterpret_cast<const quint16*>(s)[x], 0); + return qConvertRgb16To32(reinterpret_cast<const quint16 *>(s)[x]); default: - return ((QRgb*)s)[x]; + break; } + const QPixelLayout *layout = &qPixelLayouts[d->format]; + uint result; + const uint *ptr = qFetchPixels[layout->bpp](&result, s, x, 1); + return *layout->convertToARGB32PM(&result, ptr, 1, layout, 0); } @@ -3693,7 +3623,6 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) } // detach is called from within scanLine uchar * s = scanLine(y); - const quint32p p = quint32p::fromRawData(index_or_rgb); switch(d->format) { case Format_Mono: case Format_MonoLSB: @@ -3710,54 +3639,38 @@ void QImage::setPixel(int x, int y, uint index_or_rgb) else *(s + (x >> 3)) |= (1 << (7-(x & 7))); } - break; + return; case Format_Indexed8: if (index_or_rgb >= (uint)d->colortable.size()) { qWarning("QImage::setPixel: Index %d out of range", index_or_rgb); return; } s[x] = index_or_rgb; - break; + return; 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; - break; + return; case Format_ARGB32: case Format_ARGB32_Premultiplied: ((uint *)s)[x] = index_or_rgb; - break; + return; case Format_RGB16: - ((quint16 *)s)[x] = qt_colorConvert<quint16, quint32p>(p, 0); - break; - case Format_ARGB8565_Premultiplied: - ((qargb8565*)s)[x] = qt_colorConvert<qargb8565, quint32p>(p, 0); - break; - case Format_RGB666: - ((qrgb666*)s)[x] = qt_colorConvert<qrgb666, quint32p>(p, 0); - break; - case Format_ARGB6666_Premultiplied: - ((qargb6666*)s)[x] = qt_colorConvert<qargb6666, quint32p>(p, 0); - break; - case Format_RGB555: - ((qrgb555*)s)[x] = qt_colorConvert<qrgb555, quint32p>(p, 0); - break; - case Format_ARGB8555_Premultiplied: - ((qargb8555*)s)[x] = qt_colorConvert<qargb8555, quint32p>(p, 0); - break; - case Format_RGB888: - ((qrgb888*)s)[x] = qt_colorConvert<qrgb888, quint32p>(p, 0); - break; - case Format_RGB444: - ((qrgb444*)s)[x] = qt_colorConvert<qrgb444, quint32p>(p, 0); - break; - case Format_ARGB4444_Premultiplied: - ((qargb4444*)s)[x] = qt_colorConvert<qargb4444, quint32p>(p, 0); - break; + ((quint16 *)s)[x] = qConvertRgb32To16(INV_PREMUL(index_or_rgb)); + return; case Format_Invalid: case NImageFormats: Q_ASSERT(false); + return; + default: + break; } + + const QPixelLayout *layout = &qPixelLayouts[d->format]; + uint result; + const uint *ptr = layout->convertFromARGB32PM(&result, &index_or_rgb, 1, layout, 0); + qStorePixels[layout->bpp](s, ptr, x, 1); } /*! @@ -3774,30 +3687,56 @@ bool QImage::allGray() const if (!d) return true; - if (d->depth == 32) { - int p = width()*height(); - const QRgb* b = (const QRgb*)bits(); - while (p--) - if (!qIsGray(*b++)) - return false; - } else if (d->depth == 16) { - int p = width()*height(); - const ushort* b = (const ushort *)bits(); - while (p--) - if (!qIsGray(qt_colorConvert<quint32, quint16>(*b++, 0))) - return false; - } else if (d->format == QImage::Format_RGB888) { - int p = width()*height(); - const qrgb888* b = (const qrgb888 *)bits(); - while (p--) - if (!qIsGray(qt_colorConvert<quint32, qrgb888>(*b++, 0))) - return false; - } else { - if (d->colortable.isEmpty()) - return true; - for (int i = 0; i < colorCount(); i++) + switch (d->format) { + case Format_Mono: + case Format_MonoLSB: + case Format_Indexed8: + for (int i = 0; i < d->colortable.size(); ++i) { if (!qIsGray(d->colortable.at(i))) return false; + } + return true; + case Format_RGB32: + case Format_ARGB32: + case Format_ARGB32_Premultiplied: + for (int j = 0; j < d->height; ++j) { + const QRgb *b = (const QRgb *)constScanLine(j); + for (int i = 0; i < d->width; ++i) { + if (!qIsGray(b[i])) + return false; + } + } + return true; + case Format_RGB16: + for (int j = 0; j < d->height; ++j) { + const quint16 *b = (const quint16 *)constScanLine(j); + for (int i = 0; i < d->width; ++i) { + if (!qIsGray(qConvertRgb16To32(b[i]))) + return false; + } + } + return true; + default: + break; + } + + const int buffer_size = 2048; + uint buffer[buffer_size]; + const QPixelLayout *layout = &qPixelLayouts[d->format]; + FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + for (int j = 0; j < d->height; ++j) { + const uchar *b = constScanLine(j); + int x = 0; + while (x < d->width) { + int l = qMin(d->width - x, buffer_size); + const uint *ptr = fetch(buffer, b, x, l); + ptr = layout->convertToARGB32PM(buffer, ptr, l, layout, 0); + for (int i = 0; i < l; ++i) { + if (!qIsGray(ptr[i])) + return false; + } + x += l; + } } return true; } @@ -4320,7 +4259,7 @@ QImage QImage::rgbSwapped() const case Format_Invalid: case NImageFormats: Q_ASSERT(false); - break; + return res; case Format_Mono: case Format_MonoLSB: case Format_Indexed8: @@ -4329,7 +4268,7 @@ QImage QImage::rgbSwapped() const QRgb c = res.d->colortable.at(i); res.d->colortable[i] = QRgb(((c << 16) & 0xff0000) | ((c >> 16) & 0xff) | (c & 0xff00ff00)); } - break; + return res; case Format_RGB32: case Format_ARGB32: case Format_ARGB32_Premultiplied: @@ -4345,7 +4284,7 @@ QImage QImage::rgbSwapped() const q++; } } - break; + return res; case Format_RGB16: res = QImage(d->width, d->height, d->format); QIMAGE_SANITYCHECK_MEMORY(res); @@ -4359,113 +4298,41 @@ QImage QImage::rgbSwapped() const q++; } } + return res; + default: break; - case Format_ARGB8565_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - quint8 *q = res.scanLine(i); - const quint8 *end = p + d->width * sizeof(qargb8565); - while (p < end) { - q[0] = p[0]; - q[1] = (p[1] & 0xe0) | (p[2] >> 3); - q[2] = (p[2] & 0x07) | (p[1] << 3); - p += sizeof(qargb8565); - q += sizeof(qargb8565); - } - } - break; - case Format_RGB666: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - qrgb666 *q = reinterpret_cast<qrgb666*>(res.scanLine(i)); - const qrgb666 *p = reinterpret_cast<const qrgb666*>(constScanLine(i)); - const qrgb666 *end = p + d->width; - while (p < end) { - const QRgb rgb = quint32(*p++); - *q++ = qRgb(qBlue(rgb), qGreen(rgb), qRed(rgb)); - } - } - break; - case Format_ARGB6666_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - const quint8 *end = p + d->width * sizeof(qargb6666); - quint8 *q = res.scanLine(i); - while (p < end) { - q[0] = (p[1] >> 4) | ((p[2] & 0x3) << 4) | (p[0] & 0xc0); - q[1] = (p[1] & 0xf) | (p[0] << 4); - q[2] = (p[2] & 0xfc) | ((p[0] >> 4) & 0x3); - p += sizeof(qargb6666); - q += sizeof(qargb6666); - } - } - break; - case Format_RGB555: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint16 *q = (quint16*)res.scanLine(i); - const quint16 *p = (const quint16*)constScanLine(i); - const quint16 *end = p + d->width; - while (p < end) { - *q = ((*p << 10) & 0x7c00) | ((*p >> 10) & 0x1f) | (*p & 0x3e0); - p++; - q++; - } - } - break; - case Format_ARGB8555_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - const quint8 *p = constScanLine(i); - quint8 *q = res.scanLine(i); - const quint8 *end = p + d->width * sizeof(qargb8555); - while (p < end) { - q[0] = p[0]; - q[1] = (p[1] & 0xe0) | (p[2] >> 2); - q[2] = (p[2] & 0x03) | ((p[1] << 2) & 0x7f); - p += sizeof(qargb8555); - q += sizeof(qargb8555); - } - } - break; - case Format_RGB888: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint8 *q = res.scanLine(i); - const quint8 *p = constScanLine(i); - const quint8 *end = p + d->width * sizeof(qrgb888); - while (p < end) { - q[0] = p[2]; - q[1] = p[1]; - q[2] = p[0]; - q += sizeof(qrgb888); - p += sizeof(qrgb888); - } - } - break; - case Format_RGB444: - case Format_ARGB4444_Premultiplied: - res = QImage(d->width, d->height, d->format); - QIMAGE_SANITYCHECK_MEMORY(res); - for (int i = 0; i < d->height; i++) { - quint16 *q = reinterpret_cast<quint16*>(res.scanLine(i)); - const quint16 *p = reinterpret_cast<const quint16*>(constScanLine(i)); - const quint16 *end = p + d->width; - while (p < end) { - *q = (*p & 0xf0f0) | ((*p & 0x0f) << 8) | ((*p & 0xf00) >> 8); - p++; - q++; + } + + res = QImage(d->width, d->height, d->format); + QIMAGE_SANITYCHECK_MEMORY(res); + const QPixelLayout *layout = &qPixelLayouts[d->format]; + Q_ASSERT(layout->redWidth == layout->blueWidth); + FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + StorePixelsFunc store = qStorePixels[layout->bpp]; + + const uint redBlueMask = (1 << layout->redWidth) - 1; + const uint alphaGreenMask = (((1 << layout->alphaWidth) - 1) << layout->alphaShift) + | (((1 << layout->greenWidth) - 1) << layout->greenShift); + + const int buffer_size = 2048; + uint buffer[buffer_size]; + for (int i = 0; i < d->height; ++i) { + uchar *q = res.scanLine(i); + const uchar *p = constScanLine(i); + int x = 0; + while (x < d->width) { + int l = qMin(d->width - x, buffer_size); + const uint *ptr = fetch(buffer, p, x, l); + for (int j = 0; j < l; ++j) { + uint red = (ptr[j] >> layout->redShift) & redBlueMask; + uint blue = (ptr[j] >> layout->blueShift) & redBlueMask; + buffer[j] = (ptr[j] & alphaGreenMask) + | (red << layout->blueShift) + | (blue << layout->redShift); } + store(q, buffer, x, l); + x += l; } - break; } return res; } diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp index e5222fa216..382c0b8d1a 100644 --- a/src/gui/image/qpixmap_blitter.cpp +++ b/src/gui/image/qpixmap_blitter.cpp @@ -144,27 +144,11 @@ void QBlittablePlatformPixmap::fill(const QColor &color) m_alpha = true; } - uint pixel; - switch (blittable()->lock()->format()) { - case QImage::Format_ARGB32_Premultiplied: - pixel = PREMUL(color.rgba()); - break; - case QImage::Format_ARGB8565_Premultiplied: - pixel = qargb8565(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB8555_Premultiplied: - pixel = qargb8555(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB6666_Premultiplied: - pixel = qargb6666(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB4444_Premultiplied: - pixel = qargb4444(color.rgba()).rawValue(); - break; - default: - pixel = color.rgba(); - break; - } + uint pixel = PREMUL(color.rgba()); + const QPixelLayout *layout = &qPixelLayouts[blittable()->lock()->format()]; + Q_ASSERT(layout->convertFromARGB32PM); + layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); + //so premultiplied formats are supported and ARGB32 and RGB32 blittable()->lock()->fill(pixel); } diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp index 3fe5216313..8125b1360d 100644 --- a/src/gui/image/qpixmap_raster.cpp +++ b/src/gui/image/qpixmap_raster.cpp @@ -202,46 +202,10 @@ void QRasterPlatformPixmap::fill(const QColor &color) image = QImage(image.width(), image.height(), toFormat); } } - - switch (image.format()) { - case QImage::Format_ARGB8565_Premultiplied: - pixel = qargb8565(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB8555_Premultiplied: - pixel = qargb8555(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB6666_Premultiplied: - pixel = qargb6666(color.rgba()).rawValue(); - break; - case QImage::Format_ARGB4444_Premultiplied: - pixel = qargb4444(color.rgba()).rawValue(); - break; - default: - pixel = PREMUL(color.rgba()); - break; - } - } else { - switch (image.format()) { - case QImage::Format_RGB16: - pixel = qt_colorConvert<quint16, quint32>(color.rgba(), 0); - break; - case QImage::Format_RGB444: - pixel = qrgb444(color.rgba()).rawValue(); - break; - case QImage::Format_RGB555: - pixel = qrgb555(color.rgba()).rawValue(); - break; - case QImage::Format_RGB666: - pixel = qrgb666(color.rgba()).rawValue(); - break; - case QImage::Format_RGB888: - pixel = qrgb888(color.rgba()).rawValue(); - break; - default: - pixel = color.rgba(); - break; - } } + pixel = PREMUL(color.rgba()); + const QPixelLayout *layout = &qPixelLayouts[image.format()]; + layout->convertFromARGB32PM(&pixel, &pixel, 1, layout, 0); } else { pixel = 0; // ### what about 8 bits diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index a83cadb161..f17a630c8d 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -71,21 +71,6 @@ struct SourceAndConstAlpha RGB16 (565) format target format ************************************************************************/ -static inline quint16 convert_argb32_to_rgb16(quint32 spix) -{ - quint32 b = spix; - quint32 g = spix; - b >>= 8; - g >>= 5; - b &= 0x0000f800; - g &= 0x000007e0; - spix >>= 3; - b |= g; - spix &= 0x0000001f; - b |= spix; - return b; -} - struct Blend_RGB16_on_RGB16_NoAlpha { inline void write(quint16 *dst, quint16 src) { *dst = src; } @@ -108,46 +93,11 @@ struct Blend_RGB16_on_RGB16_ConstAlpha { quint32 m_ialpha; }; -struct Blend_ARGB24_on_RGB16_SourceAlpha { - inline void write(quint16 *dst, const qargb8565 &src) { - const uint alpha = src.alpha(); - if (alpha) { - quint16 s = src.rawValue16(); - if (alpha < 255) - s += BYTE_MUL_RGB16(*dst, 255 - alpha); - *dst = s; - } - } - - inline void flush(void *) {} -}; - -struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha { - inline Blend_ARGB24_on_RGB16_SourceAndConstAlpha(quint32 alpha) { - m_alpha = (alpha * 255) >> 8; - } - - inline void write(quint16 *dst, qargb8565 src) { - src = src.byte_mul(src.alpha(m_alpha)); - const uint alpha = src.alpha(); - if (alpha) { - quint16 s = src.rawValue16(); - if (alpha < 255) - s += BYTE_MUL_RGB16(*dst, 255 - alpha); - *dst = s; - } - } - - inline void flush(void *) {} - - quint32 m_alpha; -}; - struct Blend_ARGB32_on_RGB16_SourceAlpha { inline void write(quint16 *dst, quint32 src) { const quint8 alpha = qAlpha(src); - if(alpha) { - quint16 s = convert_argb32_to_rgb16(src); + if (alpha) { + quint16 s = qConvertRgb32To16(src); if(alpha < 255) s += BYTE_MUL_RGB16(*dst, 255 - alpha); *dst = s; @@ -166,7 +116,7 @@ struct Blend_ARGB32_on_RGB16_SourceAndConstAlpha { src = BYTE_MUL(src, m_alpha); const quint8 alpha = qAlpha(src); if(alpha) { - quint16 s = convert_argb32_to_rgb16(src); + quint16 s = qConvertRgb32To16(src); if(alpha < 255) s += BYTE_MUL_RGB16(*dst, 255 - alpha); *dst = s; @@ -203,32 +153,6 @@ void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl, } } -void qt_scale_image_argb24_on_rgb16(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - const QRectF &targetRect, - const QRectF &sourceRect, - const QRect &clip, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - printf("qt_scale_argb24_on_rgb16: dst=(%p, %d), src=(%p, %d), target=(%d, %d), [%d x %d], src=(%d, %d) [%d x %d] alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, - targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), - sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height(), - const_alpha); -#endif - if (const_alpha == 256) { - Blend_ARGB24_on_RGB16_SourceAlpha noAlpha; - qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl, - targetRect, sourceRect, clip, noAlpha); - } else { - Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); - qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl, - targetRect, sourceRect, clip, constAlpha); - } -} - - void qt_scale_image_argb32_on_rgb16(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, const QRectF &targetRect, @@ -280,7 +204,6 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, } } } else if (const_alpha != 0) { - SourceAndConstAlpha alpha(const_alpha); // expects the 0-256 range quint16 *d = (quint16 *) dst; const quint16 *s = (const quint16 *) src; quint8 a = (255 * const_alpha) >> 8; @@ -296,79 +219,6 @@ void qt_blend_rgb16_on_rgb16(uchar *dst, int dbpl, } -template <typename T> void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, const T &alphaFunc) -{ - int srcOffset = w*3; - int dstJPL = dbpl / 2; - quint16 *dst = (quint16 *) destPixels; - int dstExtraStride = dstJPL - w; - - for (int y=0; y<h; ++y) { - const uchar *src = srcPixels + y * sbpl; - const uchar *srcEnd = src + srcOffset; - while (src < srcEnd) { -#if defined(QT_ARCH_ARMV5) || defined(QT_ARCH_POWERPC) || defined(QT_ARCH_SH) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_WINDOWSCE) && !defined(_X86_)) || (defined(QT_ARCH_SPARC) && defined(Q_CC_GNU)) || (defined(QT_ARCH_INTEGRITY) && !defined(_X86_)) - // non-16-bit aligned memory access is not possible on PowerPC, - // ARM <v6 (QT_ARCH_ARMV5) & SH & AVR32 & SPARC w/GCC - quint16 spix = (quint16(src[2])<<8) + src[1]; -#else - quint16 spix = *(quint16 *) (src + 1); -#endif - uchar alpha = alphaFunc.alpha(*src); - - if (alpha == 255) { - *dst = spix; - } else if (alpha != 0) { - quint16 dpix = *dst; - quint32 sia = 255 - alpha; - - quint16 dr = (dpix & 0x0000f800); - quint16 dg = (dpix & 0x000007e0); - quint16 db = (dpix & 0x0000001f); - - quint32 siar = dr * sia; - quint32 siag = dg * sia; - quint32 siab = db * sia; - - quint32 rr = ((siar + (siar>>8) + (0x80 << 8)) >> 8) & 0xf800; - quint32 rg = ((siag + (siag>>8) + (0x80 << 3)) >> 8) & 0x07e0; - quint32 rb = ((siab + (siab>>8) + (0x80 >> 3)) >> 8) & 0x001f; - - *dst = alphaFunc.bytemul(spix) + rr + rg + rb; - } - - ++dst; - src += 3; - } - dst += dstExtraStride; - } - -} - -static void qt_blend_argb24_on_rgb16(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - int w, int h, - int const_alpha) -{ -#ifdef QT_DEBUG_DRAW - printf("qt_blend_argb24_on_rgb16: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n", - destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha); -#endif - - if (const_alpha != 256) { - SourceAndConstAlpha alphaFunc(const_alpha); - qt_blend_argb24_on_rgb16(destPixels, dbpl, srcPixels, sbpl, w, h, alphaFunc); - } else { - SourceOnlyAlpha alphaFunc; - qt_blend_argb24_on_rgb16(destPixels, dbpl, srcPixels, sbpl, w, h, alphaFunc); - } -} - - - - void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, int w, int h, @@ -383,7 +233,7 @@ void qt_blend_argb32_on_rgb16_const_alpha(uchar *destPixels, int dbpl, uint s = src[i]; s = BYTE_MUL(s, const_alpha); int alpha = qAlpha(s); - s = convert_argb32_to_rgb16(s); + s = qConvertRgb32To16(s); s += BYTE_MUL_RGB16(dst[i], 255 - alpha); dst[i] = s; } @@ -412,7 +262,7 @@ static void qt_blend_argb32_on_rgb16(uchar *destPixels, int dbpl, quint32 alpha = spix >> 24; if (alpha == 255) { - dst[x] = convert_argb32_to_rgb16(spix); + dst[x] = qConvertRgb32To16(spix); } else if (alpha != 0) { quint32 dpix = dst[x]; @@ -473,7 +323,7 @@ static void qt_blend_rgb32_on_rgb16(uchar *destPixels, int dbpl, while (dst < dstEnd) { const quint32 *srcEnd = src + w; while (src < srcEnd) { - *dst = convert_argb32_to_rgb16(*src); + *dst = qConvertRgb32To16(*src); ++dst; ++src; } @@ -545,19 +395,11 @@ void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl, const uint *src = (const uint *) srcPixels; uint *dst = (uint *) destPixels; - if (w <= 64) { - for (int y=0; y<h; ++y) { - qt_memconvert(dst, src, w); - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } - } else { - int len = w * 4; - for (int y=0; y<h; ++y) { - memcpy(dst, src, len); - dst = (quint32 *)(((uchar *) dst) + dbpl); - src = (const quint32 *)(((const uchar *) src) + sbpl); - } + int len = w * 4; + for (int y=0; y<h; ++y) { + memcpy(dst, src, len); + dst = (quint32 *)(((uchar *) dst) + dbpl); + src = (const quint32 *)(((const uchar *) src) + sbpl); } } @@ -681,28 +523,6 @@ void qt_transform_image_rgb16_on_rgb16(uchar *destPixels, int dbpl, } } -void qt_transform_image_argb24_on_rgb16(uchar *destPixels, int dbpl, - const uchar *srcPixels, int sbpl, - const QRectF &targetRect, - const QRectF &sourceRect, - const QRect &clip, - const QTransform &targetRectTransform, - int const_alpha) -{ - if (const_alpha == 256) { - Blend_ARGB24_on_RGB16_SourceAlpha noAlpha; - qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, - reinterpret_cast<const qargb8565 *>(srcPixels), sbpl, - targetRect, sourceRect, clip, targetRectTransform, noAlpha); - } else { - Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha); - qt_transform_image(reinterpret_cast<quint16 *>(destPixels), dbpl, - reinterpret_cast<const qargb8565 *>(srcPixels), sbpl, - targetRect, sourceRect, clip, targetRectTransform, constAlpha); - } -} - - void qt_transform_image_argb32_on_rgb16(uchar *destPixels, int dbpl, const uchar *srcPixels, int sbpl, const QRectF &targetRect, @@ -903,7 +723,7 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = 0, // Format_ARGB32, qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied, qt_scale_image_rgb16_on_rgb16, // Format_RGB16, - qt_scale_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, + 0, // Format_ARGB8565_Premultiplied, 0, // Format_RGB666, 0, // Format_ARGB6666_Premultiplied, 0, // Format_RGB555, @@ -1195,7 +1015,7 @@ SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] = 0, // Format_ARGB32, qt_blend_argb32_on_rgb16, // Format_ARGB32_Premultiplied, qt_blend_rgb16_on_rgb16, // Format_RGB16, - qt_blend_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, + 0, // Format_ARGB8565_Premultiplied, 0, // Format_RGB666, 0, // Format_ARGB6666_Premultiplied, 0, // Format_RGB555, @@ -1486,7 +1306,7 @@ SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFo 0, // Format_ARGB32, qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied, qt_transform_image_rgb16_on_rgb16, // Format_RGB16, - qt_transform_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied, + 0, // Format_ARGB8565_Premultiplied, 0, // Format_RGB666, 0, // Format_ARGB6666_Premultiplied, 0, // Format_RGB555, diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 13b8c8cae5..6a34b5c7ca 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -79,6 +79,244 @@ enum { // must be multiple of 4 for easier SIMD implementations static const int buffer_size = 2048; + + + +// To convert in place, let 'dest' and 'src' be the same. +static const uint *QT_FASTCALL convertIndexedToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *clut) +{ + for (int i = 0; i < count; ++i) + buffer[i] = PREMUL(clut[src[i]]); + return buffer; +} + +static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int, + const QPixelLayout *, const QRgb *) +{ + return src; +} + +static const uint *QT_FASTCALL convertRGB16ToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qConvertRgb16To32(src[i]); + return buffer; +} + +static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = PREMUL(src[i]); + return buffer; +} + +static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count, + const QPixelLayout *layout, const QRgb *) +{ + Q_ASSERT(layout->redWidth >= 4); + Q_ASSERT(layout->greenWidth >= 4); + Q_ASSERT(layout->blueWidth >= 4); + Q_ASSERT(layout->alphaWidth == 0); + + const uint redMask = ((1 << layout->redWidth) - 1); + const uint greenMask = ((1 << layout->greenWidth) - 1); + const uint blueMask = ((1 << layout->blueWidth) - 1); + + const uchar redLeftShift = 8 - layout->redWidth; + const uchar greenLeftShift = 8 - layout->greenWidth; + const uchar blueLeftShift = 8 - layout->blueWidth; + + const uchar redRightShift = 2 * layout->redWidth - 8; + const uchar greenRightShift = 2 * layout->greenWidth - 8; + const uchar blueRightShift = 2 * layout->blueWidth - 8; + + for (int i = 0; i < count; ++i) { + uint red = (src[i] >> layout->redShift) & redMask; + uint green = (src[i] >> layout->greenShift) & greenMask; + uint blue = (src[i] >> layout->blueShift) & blueMask; + + red = ((red << redLeftShift) | (red >> redRightShift)) << 16; + green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8; + blue = (blue << blueLeftShift) | (blue >> blueRightShift); + buffer[i] = 0xff000000 | red | green | blue; + } + + return buffer; +} + +static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *layout, const QRgb *) +{ + Q_ASSERT(layout->redWidth >= 4); + Q_ASSERT(layout->greenWidth >= 4); + Q_ASSERT(layout->blueWidth >= 4); + Q_ASSERT(layout->alphaWidth >= 4); + + const uint redMask = ((1 << layout->redWidth) - 1); + const uint greenMask = ((1 << layout->greenWidth) - 1); + const uint blueMask = ((1 << layout->blueWidth) - 1); + + const uchar redLeftShift = 8 - layout->redWidth; + const uchar greenLeftShift = 8 - layout->greenWidth; + const uchar blueLeftShift = 8 - layout->blueWidth; + + const uchar redRightShift = 2 * layout->redWidth - 8; + const uchar greenRightShift = 2 * layout->greenWidth - 8; + const uchar blueRightShift = 2 * layout->blueWidth - 8; + + const uint alphaMask = ((1 << layout->alphaWidth) - 1); + const uchar alphaLeftShift = 8 - layout->alphaWidth; + const uchar alphaRightShift = 2 * layout->alphaWidth - 8; + + if (layout->premultiplied) { + for (int i = 0; i < count; ++i) { + uint alpha = (src[i] >> layout->alphaShift) & alphaMask; + uint red = (src[i] >> layout->redShift) & redMask; + uint green = (src[i] >> layout->greenShift) & greenMask; + uint blue = (src[i] >> layout->blueShift) & blueMask; + + alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift); + red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift)); + green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift)); + blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift)); + buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue; + } + } else { + for (int i = 0; i < count; ++i) { + uint alpha = (src[i] >> layout->alphaShift) & alphaMask; + uint red = (src[i] >> layout->redShift) & redMask; + uint green = (src[i] >> layout->greenShift) & greenMask; + uint blue = (src[i] >> layout->blueShift) & blueMask; + + alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift); + 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); + } + } + return buffer; +} + +static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qConvertRgb32To16(INV_PREMUL(src[i])); + return buffer; +} + +static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = INV_PREMUL(src[i]); + return buffer; +} + +static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *layout, const QRgb *) +{ + Q_ASSERT(layout->redWidth <= 8); + Q_ASSERT(layout->greenWidth <= 8); + Q_ASSERT(layout->blueWidth <= 8); + Q_ASSERT(layout->alphaWidth <= 8); + + const uint redMask = (1 << layout->redWidth) - 1; + const uint greenMask = (1 << layout->greenWidth) - 1; + const uint blueMask = (1 << layout->blueWidth) - 1; + const uint alphaMask = (1 << layout->alphaWidth) - 1; + + const uchar redRightShift = 24 - layout->redWidth; + const uchar greenRightShift = 16 - layout->greenWidth; + const uchar blueRightShift = 8 - layout->blueWidth; + const uchar alphaRightShift = 32 - layout->alphaWidth; + + if (!layout->premultiplied) { + for (int i = 0; i < count; ++i) + buffer[i] = qAlpha(src[i]) == 255 ? src[i] : INV_PREMUL(src[i]); + src = buffer; + } + for (int i = 0; i < count; ++i) { + uint red = ((src[i] >> redRightShift) & redMask) << layout->redShift; + uint green = ((src[i] >> greenRightShift) & greenMask) << layout->greenShift; + uint blue = ((src[i] >> blueRightShift) & blueMask) << layout->blueShift; + uint alpha = ((src[i] >> alphaRightShift) & alphaMask) << layout->alphaShift; + buffer[i] = red | green | blue | alpha; + } + return buffer; +} + +// Note: +// convertToArgb32() assumes that no color channel is less than 4 bits. +// convertFromArgb32() assumes that no color channel is more than 8 bits. +// QImage::rgbSwapped() assumes that the red and blue color channels have the same number of bits. +QPixelLayout qPixelLayouts[QImage::NImageFormats] = { + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPPNone, 0, 0 }, // Format_Invalid + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1MSB, convertIndexedToARGB32PM, 0 }, // Format_Mono + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP1LSB, convertIndexedToARGB32PM, 0 }, // Format_MonoLSB + { 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertIndexedToARGB32PM, 0 }, // Format_Indexed8 + { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP32, convertPassThrough, convertPassThrough }, // Format_RGB32 + { 8, 16, 8, 8, 8, 0, 8, 24, false, QPixelLayout::BPP32, convertARGB32ToARGB32PM, convertARGB32FromARGB32PM }, // Format_ARGB32 + { 8, 16, 8, 8, 8, 0, 8, 24, true, QPixelLayout::BPP32, convertPassThrough, convertPassThrough }, // Format_ARGB32_Premultiplied + { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertRGB16ToARGB32PM, convertRGB16FromARGB32PM }, // Format_RGB16 + { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB8565_Premultiplied + { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM }, // Format_RGB666 + { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB6666_Premultiplied + { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM }, // Format_RGB555 + { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM }, // Format_ARGB8555_Premultiplied + { 8, 0, 8, 8, 8, 16, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM }, // Format_RGB888 + { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM }, // Format_RGB444 + { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertToARGB32PM, convertFromARGB32PM } // Format_ARGB4444_Premultiplied +}; + +FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = { + 0, // BPPNone + fetchPixels<QPixelLayout::BPP1MSB>, // BPP1MSB + fetchPixels<QPixelLayout::BPP1LSB>, // BPP1LSB + fetchPixels<QPixelLayout::BPP8>, // BPP8 + fetchPixels<QPixelLayout::BPP16>, // BPP16 + fetchPixels<QPixelLayout::BPP24>, // BPP24 + fetchPixels<QPixelLayout::BPP32> // BPP32 +}; + +StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = { + 0, // BPPNone + storePixels<QPixelLayout::BPP1MSB>, // BPP1MSB + storePixels<QPixelLayout::BPP1LSB>, // BPP1LSB + storePixels<QPixelLayout::BPP8>, // BPP8 + storePixels<QPixelLayout::BPP16>, // BPP16 + storePixels<QPixelLayout::BPP24>, // BPP24 + storePixels<QPixelLayout::BPP32> // BPP32 +}; + +typedef uint (QT_FASTCALL *FetchPixelFunc)(const uchar *src, int index); +typedef void (QT_FASTCALL *StorePixelFunc)(uchar *dest, int index, uint pixel); + +FetchPixelFunc qFetchPixel[QPixelLayout::BPPCount] = { + 0, // BPPNone + fetchPixel<QPixelLayout::BPP1MSB>, // BPP1MSB + fetchPixel<QPixelLayout::BPP1LSB>, // BPP1LSB + fetchPixel<QPixelLayout::BPP8>, // BPP8 + fetchPixel<QPixelLayout::BPP16>, // BPP16 + fetchPixel<QPixelLayout::BPP24>, // BPP24 + fetchPixel<QPixelLayout::BPP32> // BPP32 +}; + +StorePixelFunc qStorePixel[QPixelLayout::BPPCount] = { + 0, // BPPNone + storePixel<QPixelLayout::BPP1MSB>, // BPP1MSB + storePixel<QPixelLayout::BPP1LSB>, // BPP1LSB + storePixel<QPixelLayout::BPP8>, // BPP8 + storePixel<QPixelLayout::BPP16>, // BPP16 + storePixel<QPixelLayout::BPP24>, // BPP24 + storePixel<QPixelLayout::BPP32> // BPP32 +}; + + /* Destination fetch. This is simple as we don't have to do bounds checks or transformations @@ -110,14 +348,6 @@ static uint * QT_FASTCALL destFetchMonoLsb(uint *buffer, QRasterBuffer *rasterBu return start; } -static uint * QT_FASTCALL destFetchARGB32(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) -{ - const uint *data = (const uint *)rasterBuffer->scanLine(y) + x; - for (int i = 0; i < length; ++i) - buffer[i] = PREMUL(data[i]); - return buffer; -} - static uint * QT_FASTCALL destFetchARGB32P(uint *, QRasterBuffer *rasterBuffer, int x, int y, int) { return (uint *)rasterBuffer->scanLine(y) + x; @@ -131,37 +361,32 @@ static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuff return buffer; } -template <class DST> -Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, - int x, int y, int length) +static uint *QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) { - const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; - quint32 *dest = reinterpret_cast<quint32*>(buffer); - while (length--) - *dest++ = *src++; - return buffer; + const QPixelLayout *layout = &qPixelLayouts[rasterBuffer->format]; + const uint *ptr = qFetchPixels[layout->bpp](buffer, rasterBuffer->scanLine(y), x, length); + return const_cast<uint *>(layout->convertToARGB32PM(buffer, ptr, length, layout, 0)); } -# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg> static DestFetchProc destFetchProc[QImage::NImageFormats] = { - 0, // Format_Invalid - destFetchMono, // Format_Mono, - destFetchMonoLsb, // Format_MonoLSB - 0, // Format_Indexed8 - destFetchARGB32P, // Format_RGB32 - destFetchARGB32, // Format_ARGB32, - destFetchARGB32P, // Format_ARGB32_Premultiplied - destFetchRGB16, // Format_RGB16 - SPANFUNC_POINTER_DESTFETCH(qargb8565), // Format_ARGB8565_Premultiplied - SPANFUNC_POINTER_DESTFETCH(qrgb666), // Format_RGB666 - SPANFUNC_POINTER_DESTFETCH(qargb6666), // Format_ARGB6666_Premultiplied - SPANFUNC_POINTER_DESTFETCH(qrgb555), // Format_RGB555 - SPANFUNC_POINTER_DESTFETCH(qargb8555), // Format_ARGB8555_Premultiplied - SPANFUNC_POINTER_DESTFETCH(qrgb888), // Format_RGB888 - SPANFUNC_POINTER_DESTFETCH(qrgb444), // Format_RGB444 - SPANFUNC_POINTER_DESTFETCH(qargb4444) // Format_ARGB4444_Premultiplied + 0, // Format_Invalid + destFetchMono, // Format_Mono, + destFetchMonoLsb, // Format_MonoLSB + 0, // Format_Indexed8 + destFetchARGB32P, // Format_RGB32 + destFetch, // Format_ARGB32, + destFetchARGB32P, // Format_ARGB32_Premultiplied + destFetchRGB16, // Format_RGB16 + destFetch, // Format_ARGB8565_Premultiplied + destFetch, // Format_RGB666 + destFetch, // Format_ARGB6666_Premultiplied + destFetch, // Format_RGB555 + destFetch, // Format_ARGB8555_Premultiplied + destFetch, // Format_RGB888 + destFetch, // Format_RGB444 + destFetch // Format_ARGB4444_Premultiplied }; /* @@ -253,63 +478,47 @@ static void QT_FASTCALL destStoreMonoLsb(QRasterBuffer *rasterBuffer, int x, int } } -static void QT_FASTCALL destStoreARGB32(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) -{ - uint *data = (uint *)rasterBuffer->scanLine(y) + x; - for (int i = 0; i < length; ++i) { - int p = buffer[i]; - int alpha = qAlpha(p); - if (alpha == 255) - data[i] = p; - else if (alpha == 0) - data[i] = 0; - else { - int inv_alpha = 0xff0000/qAlpha(buffer[i]); - data[i] = (p & 0xff000000) - | ((qRed(p)*inv_alpha) & 0xff0000) - | (((qGreen(p)*inv_alpha) >> 8) & 0xff00) - | ((qBlue(p)*inv_alpha) >> 16); - } - } -} - static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) { quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x; - qt_memconvert<quint16, quint32>(data, buffer, length); + for (int i = 0; i < length; ++i) + data[i] = qConvertRgb32To16(buffer[i]); } -template <class DST> -Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, - int x, int y, - const uint *buffer, int length) +static void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) { - DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; - const quint32p *src = reinterpret_cast<const quint32p*>(buffer); - while (length--) - *dest++ = DST(*src++); + 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 = layout->convertFromARGB32PM(buf, buffer, l, layout, 0); + store(dest, ptr, x, l); + length -= l; + buffer += l; + x += l; + } } -# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST> - static DestStoreProc destStoreProc[QImage::NImageFormats] = { - 0, // Format_Invalid - destStoreMono, // Format_Mono, - destStoreMonoLsb, // Format_MonoLSB - 0, // Format_Indexed8 - 0, // Format_RGB32 - destStoreARGB32, // Format_ARGB32, - 0, // Format_ARGB32_Premultiplied - destStoreRGB16, // Format_RGB16 - SPANFUNC_POINTER_DESTSTORE(qargb8565), // Format_ARGB8565_Premultiplied - SPANFUNC_POINTER_DESTSTORE(qrgb666), // Format_RGB666 - SPANFUNC_POINTER_DESTSTORE(qargb6666), // Format_ARGB6666_Premultiplied - SPANFUNC_POINTER_DESTSTORE(qrgb555), // Format_RGB555 - SPANFUNC_POINTER_DESTSTORE(qargb8555), // Format_ARGB8555_Premultiplied - SPANFUNC_POINTER_DESTSTORE(qrgb888), // Format_RGB888 - SPANFUNC_POINTER_DESTSTORE(qrgb444), // Format_RGB444 - SPANFUNC_POINTER_DESTSTORE(qargb4444) // Format_ARGB4444_Premultiplied + 0, // Format_Invalid + destStoreMono, // Format_Mono, + destStoreMonoLsb, // Format_MonoLSB + 0, // Format_Indexed8 + 0, // Format_RGB32 + destStore, // Format_ARGB32, + 0, // Format_ARGB32_Premultiplied + destStoreRGB16, // Format_RGB16 + destStore, // Format_ARGB8565_Premultiplied + destStore, // Format_RGB666 + destStore, // Format_ARGB6666_Premultiplied + destStore, // Format_RGB555 + destStore, // Format_ARGB8555_Premultiplied + destStore, // Format_RGB888 + destStore, // Format_RGB444 + destStore // Format_ARGB4444_Premultiplied }; /* @@ -327,218 +536,139 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] = The generic implementation does pixel by pixel fetches */ -template <QImage::Format format> -Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb); - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb) -{ - bool pixel = scanLine[x>>3] & (0x80 >> (x & 7)); - if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); - return pixel ? 0xff000000 : 0xffffffff; -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb) -{ - bool pixel = scanLine[x>>3] & (0x1 << (x & 7)); - if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); - return pixel ? 0xff000000 : 0xffffffff; -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine, - int x, const QVector<QRgb> *rgb) -{ - return PREMUL(rgb->at(scanLine[x])); -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine, - int x, const QVector<QRgb> *) -{ - return PREMUL(((const uint *)scanLine)[x]); -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine, - int x, const QVector<QRgb> *) -{ - return ((const uint *)scanLine)[x]; -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine, - int x, const QVector<QRgb> *) -{ - return qConvertRgb16To32(((const ushort *)scanLine)[x]); -} - -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine, - int x, - const QVector<QRgb> *) -{ - const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x]; - return qt_colorConvert<quint32, qargb8565>(color, 0); -} +enum TextureBlendType { + BlendUntransformed, + BlendTiled, + BlendTransformed, + BlendTransformedTiled, + BlendTransformedBilinear, + BlendTransformedBilinearTiled, + NBlendTypes +}; -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine, - int x, - const QVector<QRgb> *) +static const uint *QT_FASTCALL fetchUntransformed(uint *buffer, const Operator *, + const QSpanData *data, int y, int x, int length) { - const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x]; - return qt_colorConvert<quint32, qrgb666>(color, 0); + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + const uint *ptr = qFetchPixels[layout->bpp](buffer, data->texture.scanLine(y), x, length); + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + return layout->convertToARGB32PM(buffer, ptr, length, layout, clut); } -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine, - int x, - const QVector<QRgb> *) +static const uint *QT_FASTCALL fetchUntransformedARGB32PM(uint *, const Operator *, + const QSpanData *data, int y, int x, int) { - const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x]; - return qt_colorConvert<quint32, qargb6666>(color, 0); + const uchar *scanLine = data->texture.scanLine(y); + return ((const uint *)scanLine) + x; } -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine, - int x, - const QVector<QRgb> *) +static const uint *QT_FASTCALL fetchUntransformedRGB16(uint *buffer, const Operator *, + const QSpanData *data, int y, int x, + int length) { - const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x]; - return qt_colorConvert<quint32, qrgb555>(color, 0); + const quint16 *scanLine = (const quint16 *)data->texture.scanLine(y) + x; + for (int i = 0; i < length; ++i) + buffer[i] = qConvertRgb16To32(scanLine[i]); + return buffer; } -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine, - int x, - const QVector<QRgb> *) +// blendType is either BlendTransformed or BlendTransformedTiled +template<TextureBlendType blendType> +Q_STATIC_TEMPLATE_FUNCTION +const uint *QT_FASTCALL fetchTransformedARGB32PM(uint *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) { - const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x]; - return qt_colorConvert<quint32, qargb8555>(color, 0); -} + int image_width = data->texture.width; + int image_height = data->texture.height; -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine, - int x, - const QVector<QRgb> *) -{ - const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x]; - return qt_colorConvert<quint32, qrgb888>(color, 0); -} + const qreal cx = x + qreal(0.5); + const qreal cy = y + qreal(0.5); -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine, - int x, - const QVector<QRgb> *) -{ - const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x]; - return qt_colorConvert<quint32, qrgb444>(color, 0); -} + const uint *end = buffer + length; + uint *b = buffer; + if (data->fast_matrix) { + // The increment pr x in the scanline + int fdx = (int)(data->m11 * fixed_scale); + int fdy = (int)(data->m12 * fixed_scale); -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine, - int x, - const QVector<QRgb> *) -{ - const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x]; - return qt_colorConvert<quint32, qargb4444>(color, 0); -} + int fx = int((data->m21 * cy + + data->m11 * cx + data->dx) * fixed_scale); + int fy = int((data->m22 * cy + + data->m12 * cx + data->dy) * fixed_scale); -template<> -Q_STATIC_TEMPLATE_SPECIALIZATION -uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *, - int , - const QVector<QRgb> *) -{ - return 0; -} + while (b < end) { + int px = fx >> 16; + int py = fy >> 16; -typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *); + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; + } else { + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); + } + *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; -#define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg> + fx += fdx; + fy += fdy; + ++b; + } + } else { + const qreal fdx = data->m11; + const qreal fdy = data->m12; + const qreal fdw = data->m13; + qreal fx = data->m21 * cy + data->m11 * cx + data->dx; + qreal fy = data->m22 * cy + data->m12 * cx + data->dy; + qreal fw = data->m23 * cy + data->m13 * cx + data->m33; -static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] = -{ - 0, - SPANFUNC_POINTER_FETCHPIXEL(Format_Mono), - SPANFUNC_POINTER_FETCHPIXEL(Format_MonoLSB), - SPANFUNC_POINTER_FETCHPIXEL(Format_Indexed8), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), - SPANFUNC_POINTER_FETCHPIXEL(Format_RGB16), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8565_Premultiplied), - SPANFUNC_POINTER_FETCHPIXEL(Format_RGB666), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB6666_Premultiplied), - SPANFUNC_POINTER_FETCHPIXEL(Format_RGB555), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8555_Premultiplied), - SPANFUNC_POINTER_FETCHPIXEL(Format_RGB888), - SPANFUNC_POINTER_FETCHPIXEL(Format_RGB444), - SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB4444_Premultiplied) -}; + while (b < end) { + const qreal iw = fw == 0 ? 1 : 1 / fw; + const qreal tx = fx * iw; + const qreal ty = fy * iw; + int px = int(tx) - (tx < 0); + int py = int(ty) - (ty < 0); -enum TextureBlendType { - BlendUntransformed, - BlendTiled, - BlendTransformed, - BlendTransformedTiled, - BlendTransformedBilinear, - BlendTransformedBilinearTiled, - NBlendTypes -}; + if (blendType == BlendTransformedTiled) { + px %= image_width; + py %= image_height; + if (px < 0) px += image_width; + if (py < 0) py += image_height; + } else { + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); + } + *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; -template <QImage::Format format> -Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) -{ - const uchar *scanLine = data->texture.scanLine(y); - for (int i = 0; i < length; ++i) - buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable); + fx += fdx; + fy += fdy; + fw += fdw; + //force increment to avoid /0 + if (!fw) { + fw += fdw; + } + ++b; + } + } return buffer; } -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL -qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *, - const QSpanData *data, - int y, int x, int) -{ - const uchar *scanLine = data->texture.scanLine(y); - return ((const uint *)scanLine) + x; -} - template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ Q_STATIC_TEMPLATE_FUNCTION -const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) +const uint *QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, + int y, int x, int length) { - FetchPixelProc fetch = fetchPixelProc[data->texture.format]; - int image_width = data->texture.width; int image_height = data->texture.height; const qreal cx = x + qreal(0.5); const qreal cy = y + qreal(0.5); + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + const uint *end = buffer + length; uint *b = buffer; if (data->fast_matrix) { @@ -560,18 +690,12 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const py %= image_height; if (px < 0) px += image_width; if (py < 0) py += image_height; - - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); } else { - if ((px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height)) { - *b = uint(0); - } else { - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); - } + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); } + *b = fetch(data->texture.scanLine(py), px); + fx += fdx; fy += fdy; ++b; @@ -597,18 +721,12 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const py %= image_height; if (px < 0) px += image_width; if (py < 0) py += image_height; - - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); } else { - if ((px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height)) { - *b = uint(0); - } else { - const uchar *scanLine = data->texture.scanLine(py); - *b = fetch(scanLine, px, data->texture.colorTable); - } + px = qBound(0, px, image_width - 1); + py = qBound(0, py, image_height - 1); } + *b = fetch(data->texture.scanLine(py), px); + fx += fdx; fy += fdy; fw += fdw; @@ -619,8 +737,8 @@ const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const ++b; } } - - return buffer; + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + return layout->convertToARGB32PM(buffer, buffer, length, layout, clut); } /** \internal @@ -714,42 +832,42 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i #endif template<TextureBlendType blendType> -Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) -{ - if (blendType == BlendTransformedBilinearTiled) { - v1 %= max; - if (v1 < 0) v1 += max; - v2 = v1 + 1; - v2 %= max; - } else { - if (v1 < l1) { - v2 = v1 = l1; - } else if (v1 >= l2) { - v2 = v1 = l2; - } else { - v2 = v1 + 1; - } - } +void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2); +template<> +Q_STATIC_TEMPLATE_SPECIALIZATION +inline void fetchTransformedBilinear_pixelBounds<BlendTransformedBilinearTiled>(int max, int, int, int &v1, int &v2) +{ + v1 %= max; + if (v1 < 0) + v1 += max; + v2 = v1 + 1; + if (v2 == max) + v2 = 0; Q_ASSERT(v1 >= 0 && v1 < max); Q_ASSERT(v2 >= 0 && v2 < max); } -template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ -Q_STATIC_TEMPLATE_FUNCTION -const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, - int y, int x, int length) +template<> +Q_STATIC_TEMPLATE_SPECIALIZATION +inline void fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(int, int l1, int l2, int &v1, int &v2) { -#ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 - FetchPixelProc fetch; - if (format != QImage::Format_Invalid) - fetch = qt_fetchPixel<format>; + if (v1 < l1) + v2 = v1 = l1; + else if (v1 >= l2) + v2 = v1 = l2; else - fetch = fetchPixelProc[data->texture.format]; -#else - FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; -#endif + v2 = v1 + 1; + Q_ASSERT(v1 >= l1 && v1 <= l2); + Q_ASSERT(v2 >= l1 && v2 <= l2); +} +template<TextureBlendType blendType> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ +Q_STATIC_TEMPLATE_FUNCTION +const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, const Operator *, + const QSpanData *data, int y, int x, + int length) +{ int image_width = data->texture.width; int image_height = data->texture.height; @@ -780,8 +898,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int y1 = (fy >> 16); int y2; fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); if (fdx <= fixed_scale && fdx > 0) { // scale up on X int disty = (fy & 0x0000ffff) >> 8; @@ -806,8 +924,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * lim = qMin(count, image_x2-x+1); if (x < image_x1) { Q_ASSERT(x <= image_x2); - uint t = fetch(s1, image_x1, data->texture.colorTable); - uint b = fetch(s2, image_x1, data->texture.colorTable); + uint t = s1[image_x1]; + uint b = s2[image_x1]; quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; do { @@ -819,8 +937,7 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * } } - if (blendType != BlendTransformedBilinearTiled && - (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { + if (blendType != BlendTransformedBilinearTiled) { #if defined(QT_ALWAYS_HAVE_SSE2) const __m128i disty_ = _mm_set1_epi16(disty); const __m128i idisty_ = _mm_set1_epi16(idisty); @@ -890,8 +1007,8 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * x = qMin(x, image_x2); } - uint t = fetch(s1, x, data->texture.colorTable); - uint b = fetch(s2, x, data->texture.colorTable); + uint t = s1[x]; + uint b = s2[x]; intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; @@ -918,18 +1035,18 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int y1 = (fy >> 16); int y2; fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); int disty = (fy & 0x0000ffff) >> 8; int idisty = 256 - disty; while (b < end) { int x1 = (fx >> 16); int x2; fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = s1[x1]; + uint tr = s1[x2]; + uint bl = s2[x1]; + uint br = s2[x2]; int distx = (fx & 0x0000ffff) >> 8; int idistx = 256 - distx; @@ -945,13 +1062,11 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int y1 = (fy >> 16); int y2; fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); int disty = (fy & 0x0000ffff) >> 12; - if (blendType != BlendTransformedBilinearTiled && - (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { - + if (blendType != BlendTransformedBilinearTiled) { #define BILINEAR_DOWNSCALE_BOUNDS_PROLOG \ while (b < end) { \ int x1 = (fx >> 16); \ @@ -959,10 +1074,10 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \ if (x1 != x2) \ break; \ - uint tl = fetch(s1, x1, data->texture.colorTable); \ - uint tr = fetch(s1, x2, data->texture.colorTable); \ - uint bl = fetch(s2, x1, data->texture.colorTable); \ - uint br = fetch(s2, x2, data->texture.colorTable); \ + uint tl = s1[x1]; \ + uint tr = s1[x2]; \ + uint bl = s2[x1]; \ + uint br = s2[x2]; \ int distx = (fx & 0x0000ffff) >> 12; \ *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \ fx += fdx; \ @@ -1070,10 +1185,10 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * int x1 = (fx >> 16); int x2; fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = s1[x1]; + uint tr = s1[x2]; + uint bl = s2[x1]; + uint br = s2[x2]; int distx = (fx & 0x0000ffff) >> 12; *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); fx += fdx; @@ -1092,13 +1207,13 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = s1[x1]; + uint tr = s1[x2]; + uint bl = s2[x1]; + uint br = s2[x2]; int distx = (fx & 0x0000ffff) >> 8; int disty = (fy & 0x0000ffff) >> 8; @@ -1124,13 +1239,13 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = s1[x1]; + uint tr = s1[x2]; + uint bl = s2[x1]; + uint br = s2[x2]; int distx = (fx & 0x0000ffff) >> 12; int disty = (fy & 0x0000ffff) >> 12; @@ -1170,13 +1285,13 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); - const uchar *s1 = data->texture.scanLine(y1); - const uchar *s2 = data->texture.scanLine(y2); + const uint *s1 = (const uint *)data->texture.scanLine(y1); + const uint *s2 = (const uint *)data->texture.scanLine(y2); - uint tl = fetch(s1, x1, data->texture.colorTable); - uint tr = fetch(s1, x2, data->texture.colorTable); - uint bl = fetch(s2, x1, data->texture.colorTable); - uint br = fetch(s2, x2, data->texture.colorTable); + uint tl = s1[x1]; + uint tr = s1[x2]; + uint bl = s2[x1]; + uint br = s2[x2]; uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); @@ -1196,119 +1311,452 @@ const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator * return buffer; } -#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg> +// blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled +template<TextureBlendType blendType> +Q_STATIC_TEMPLATE_FUNCTION +const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, + const QSpanData *data, int y, int x, int length) +{ + const QPixelLayout *layout = &qPixelLayouts[data->texture.format]; + const QRgb *clut = data->texture.colorTable ? data->texture.colorTable->constData() : 0; + + int image_width = data->texture.width; + int image_height = data->texture.height; + + int image_x1 = data->texture.x1; + int image_y1 = data->texture.y1; + int image_x2 = data->texture.x2 - 1; + int image_y2 = data->texture.y2 - 1; + + const qreal cx = x + qreal(0.5); + const qreal cy = y + qreal(0.5); + + if (data->fast_matrix) { + // The increment pr x in the scanline + int fdx = (int)(data->m11 * fixed_scale); + int fdy = (int)(data->m12 * fixed_scale); + + int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale); + int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale); + + fx -= half_point; + fy -= half_point; + + if (fdy == 0) { //simple scale, no rotation + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + if (fdx <= fixed_scale && fdx > 0) { // scale up on X + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + int x = fx >> 16; + + // The idea is first to do the interpolation between the row s1 and the row s2 + // into an intermediate buffer, then we interpolate between two pixel of this buffer. + FetchPixelsFunc fetch = qFetchPixels[layout->bpp]; + uint buf1[buffer_size + 2]; + uint buf2[buffer_size + 2]; + const uint *ptr1; + const uint *ptr2; + + int count = qCeil(length * data->m11) + 2; //+1 for the last pixel to interpolate with, and +1 for rounding errors. + Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case + + if (blendType == BlendTransformedBilinearTiled) { + x %= image_width; + if (x < 0) + x += image_width; + int len1 = qMin(count, image_width - x); + int len2 = qMin(x, count - len1); + + ptr1 = fetch(buf1, s1, x, len1); + ptr1 = layout->convertToARGB32PM(buf1, ptr1, len1, layout, clut); + ptr2 = fetch(buf2, s2, x, len1); + ptr2 = layout->convertToARGB32PM(buf2, ptr2, len1, layout, clut); + for (int i = 0; i < len1; ++i) { + uint t = ptr1[i]; + uint b = ptr2[i]; + buf1[i] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + buf2[i] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + } + + if (len2) { + ptr1 = fetch(buf1 + len1, s1, 0, len2); + ptr1 = layout->convertToARGB32PM(buf1 + len1, ptr1, len2, layout, clut); + ptr2 = fetch(buf2 + len1, s2, 0, len2); + ptr2 = layout->convertToARGB32PM(buf2 + len1, ptr2, len2, layout, clut); + for (int i = 0; i < len2; ++i) { + uint t = ptr1[i]; + uint b = ptr2[i]; + buf1[i + len1] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + } + } + for (int i = image_width; i < count; ++i) { + buf1[i] = buf1[i - image_width]; + buf2[i] = buf2[i - image_width]; + } + } else { + int start = qMax(x, image_x1); + int end = qMin(x + count, image_x2 + 1); + int len = qMax(1, end - start); + int leading = start - x; + + ptr1 = fetch(buf1 + leading, s1, start, len); + ptr1 = layout->convertToARGB32PM(buf1 + leading, ptr1, len, layout, clut); + ptr2 = fetch(buf2 + leading, s2, start, len); + ptr2 = layout->convertToARGB32PM(buf2 + leading, ptr2, len, layout, clut); + + for (int i = 0; i < len; ++i) { + uint t = ptr1[i]; + uint b = ptr2[i]; + buf1[i + leading] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; + buf2[i + leading] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff; + } + + for (int i = 0; i < leading; ++i) { + buf1[i] = buf1[leading]; + buf2[i] = buf2[leading]; + } + for (int i = leading + len; i < count; ++i) { + buf1[i] = buf1[i - 1]; + buf2[i] = buf2[i - 1]; + } + } + + // Now interpolate the values from the intermediate_buffer to get the final result. + fx &= fixed_scale - 1; + Q_ASSERT((fx >> 16) == 0); + for (int i = 0; i < length; ++i) { + register int x1 = (fx >> 16); + register int x2 = x1 + 1; + Q_ASSERT(x1 >= 0); + Q_ASSERT(x2 < count); + + register int distx = (fx & 0x0000ffff) >> 8; + register int idistx = 256 - distx; + int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff; + int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00; + buffer[i] = rb | ag; + fx += fdx; + } + } else { + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint buf1[buffer_size]; + uint buf2[buffer_size]; + uint *b = buffer; + while (length) { + int len = qMin(length, buffer_size / 2); + int fracX = fx; + for (int i = 0; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + + buf1[i * 2 + 0] = fetch(s1, x1); + buf1[i * 2 + 1] = fetch(s1, x2); + buf2[i * 2 + 0] = fetch(s2, x1); + buf2[i * 2 + 1] = fetch(s2, x2); + + fx += fdx; + } + layout->convertToARGB32PM(buf1, buf1, len * 2, layout, clut); + layout->convertToARGB32PM(buf2, buf2, len * 2, layout, clut); + + if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x + int disty = (fy & 0x0000ffff) >> 8; + int idisty = 256 - disty; + for (int i = 0; i < len; ++i) { + uint tl = buf1[i * 2 + 0]; + uint tr = buf1[i * 2 + 1]; + uint bl = buf2[i * 2 + 0]; + uint br = buf2[i * 2 + 1]; + int distx = (fracX & 0x0000ffff) >> 8; + int idistx = 256 - distx; + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + fracX += fdx; + } + } else { //scale down + int disty = (fy & 0x0000ffff) >> 12; + for (int i = 0; i < len; ++i) { + uint tl = buf1[i * 2 + 0]; + uint tr = buf1[i * 2 + 1]; + uint bl = buf2[i * 2 + 0]; + uint br = buf2[i * 2 + 1]; + int distx = (fracX & 0x0000ffff) >> 12; + b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); + fracX += fdx; + } + } + length -= len; + b += len; + } + } + } else { //rotation + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint buf1[buffer_size]; + uint buf2[buffer_size]; + uint *b = buffer; + + while (length) { + int len = qMin(length, buffer_size / 2); + int fracX = fx; + int fracY = fy; + for (int i = 0; i < len; ++i) { + int x1 = (fx >> 16); + int x2; + int y1 = (fy >> 16); + int y2; + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + buf1[i * 2 + 0] = fetch(s1, x1); + buf1[i * 2 + 1] = fetch(s1, x2); + buf2[i * 2 + 0] = fetch(s2, x1); + buf2[i * 2 + 1] = fetch(s2, x2); + + fx += fdx; + fy += fdy; + } + layout->convertToARGB32PM(buf1, buf1, len * 2, layout, clut); + layout->convertToARGB32PM(buf2, buf2, len * 2, layout, clut); + + if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { + //if we are zooming more than 8 times, we use 8bit precision for the position. + for (int i = 0; i < len; ++i) { + uint tl = buf1[i * 2 + 0]; + uint tr = buf1[i * 2 + 1]; + uint bl = buf2[i * 2 + 0]; + uint br = buf2[i * 2 + 1]; + + int distx = (fracX & 0x0000ffff) >> 8; + int disty = (fracY & 0x0000ffff) >> 8; + int idistx = 256 - distx; + int idisty = 256 - disty; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + fracX += fdx; + fracY += fdy; + } + } else { + //we are zooming less than 8x, use 4bit precision + for (int i = 0; i < len; ++i) { + uint tl = buf1[i * 2 + 0]; + uint tr = buf1[i * 2 + 1]; + uint bl = buf2[i * 2 + 0]; + uint br = buf2[i * 2 + 1]; + + int distx = (fracX & 0x0000ffff) >> 12; + int disty = (fracY & 0x0000ffff) >> 12; + + b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); + fracX += fdx; + fracY += fdy; + } + } + + length -= len; + b += len; + } + } + } else { + const qreal fdx = data->m11; + const qreal fdy = data->m12; + const qreal fdw = data->m13; + + qreal fx = data->m21 * cy + data->m11 * cx + data->dx; + qreal fy = data->m22 * cy + data->m12 * cx + data->dy; + qreal fw = data->m23 * cy + data->m13 * cx + data->m33; + + FetchPixelFunc fetch = qFetchPixel[layout->bpp]; + uint buf1[buffer_size]; + uint buf2[buffer_size]; + uint *b = buffer; + + int distxs[buffer_size / 2]; + int distys[buffer_size / 2]; + + while (length) { + int len = qMin(length, buffer_size / 2); + for (int i = 0; i < len; ++i) { + const qreal iw = fw == 0 ? 1 : 1 / fw; + const qreal px = fx * iw - qreal(0.5); + const qreal py = fy * iw - qreal(0.5); + + int x1 = int(px) - (px < 0); + int x2; + int y1 = int(py) - (py < 0); + int y2; + + distxs[i] = int((px - x1) * 256); + distys[i] = int((py - y1) * 256); + + fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); + fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); + + const uchar *s1 = data->texture.scanLine(y1); + const uchar *s2 = data->texture.scanLine(y2); + + buf1[i * 2 + 0] = fetch(s1, x1); + buf1[i * 2 + 1] = fetch(s1, x2); + buf2[i * 2 + 0] = fetch(s2, x1); + buf2[i * 2 + 1] = fetch(s2, x2); + + fx += fdx; + fy += fdy; + fw += fdw; + //force increment to avoid /0 + if (!fw) + fw += fdw; + } + + layout->convertToARGB32PM(buf1, buf1, len * 2, layout, clut); + layout->convertToARGB32PM(buf2, buf2, len * 2, layout, clut); + + for (int i = 0; i < len; ++i) { + int distx = distxs[i]; + int disty = distys[i]; + int idistx = 256 - distx; + int idisty = 256 - disty; + + uint tl = buf1[i * 2 + 0]; + uint tr = buf1[i * 2 + 1]; + uint bl = buf2[i * 2 + 0]; + uint br = buf2[i * 2 + 1]; + + uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); + uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); + b[i] = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); + } + length -= len; + b += len; + } + } + + return buffer; +} static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { // Untransformed { 0, // Invalid - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied + fetchUntransformed, // Mono + fetchUntransformed, // MonoLsb + fetchUntransformed, // Indexed8 + fetchUntransformedARGB32PM, // RGB32 + fetchUntransformed, // ARGB32 + fetchUntransformedARGB32PM, // ARGB32_Premultiplied + fetchUntransformedRGB16, // RGB16 + fetchUntransformed, // ARGB8565_Premultiplied + fetchUntransformed, // RGB666 + fetchUntransformed, // ARGB6666_Premultiplied + fetchUntransformed, // RGB555 + fetchUntransformed, // ARGB8555_Premultiplied + fetchUntransformed, // RGB888 + fetchUntransformed, // RGB444 + fetchUntransformed // ARGB4444_Premultiplied }, // Tiled { 0, // Invalid - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 - SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied + fetchUntransformed, // Mono + fetchUntransformed, // MonoLsb + fetchUntransformed, // Indexed8 + fetchUntransformedARGB32PM, // RGB32 + fetchUntransformed, // ARGB32 + fetchUntransformedARGB32PM, // ARGB32_Premultiplied + fetchUntransformedRGB16, // RGB16 + fetchUntransformed, // ARGB8565_Premultiplied + fetchUntransformed, // RGB666 + fetchUntransformed, // ARGB6666_Premultiplied + fetchUntransformed, // RGB555 + fetchUntransformed, // ARGB8555_Premultiplied + fetchUntransformed, // RGB888 + fetchUntransformed, // RGB444 + fetchUntransformed // ARGB4444_Premultiplied }, // Transformed { 0, // Invalid - fetchTransformed<BlendTransformed>, // Mono - fetchTransformed<BlendTransformed>, // MonoLsb - fetchTransformed<BlendTransformed>, // Indexed8 - fetchTransformed<BlendTransformed>, // RGB32 - fetchTransformed<BlendTransformed>, // ARGB32 - fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied - fetchTransformed<BlendTransformed>, // RGB16 - fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied - fetchTransformed<BlendTransformed>, // RGB666 - fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied - fetchTransformed<BlendTransformed>, // RGB555 - fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied - fetchTransformed<BlendTransformed>, // RGB888 - fetchTransformed<BlendTransformed>, // RGB444 - fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied + fetchTransformed<BlendTransformed>, // Mono + fetchTransformed<BlendTransformed>, // MonoLsb + fetchTransformed<BlendTransformed>, // Indexed8 + fetchTransformedARGB32PM<BlendTransformed>, // RGB32 + fetchTransformed<BlendTransformed>, // ARGB32 + fetchTransformedARGB32PM<BlendTransformed>, // ARGB32_Premultiplied + fetchTransformed<BlendTransformed>, // RGB16 + fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied + fetchTransformed<BlendTransformed>, // RGB666 + fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied + fetchTransformed<BlendTransformed>, // RGB555 + fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied + fetchTransformed<BlendTransformed>, // RGB888 + fetchTransformed<BlendTransformed>, // RGB444 + fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied }, { 0, // TransformedTiled - fetchTransformed<BlendTransformedTiled>, // Mono - fetchTransformed<BlendTransformedTiled>, // MonoLsb - fetchTransformed<BlendTransformedTiled>, // Indexed8 - fetchTransformed<BlendTransformedTiled>, // RGB32 - fetchTransformed<BlendTransformedTiled>, // ARGB32 - fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied - fetchTransformed<BlendTransformedTiled>, // RGB16 - fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied - fetchTransformed<BlendTransformedTiled>, // RGB666 - fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied - fetchTransformed<BlendTransformedTiled>, // RGB555 - fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied - fetchTransformed<BlendTransformedTiled>, // RGB888 - fetchTransformed<BlendTransformedTiled>, // RGB444 - fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied + fetchTransformed<BlendTransformedTiled>, // Mono + fetchTransformed<BlendTransformedTiled>, // MonoLsb + fetchTransformed<BlendTransformedTiled>, // Indexed8 + fetchTransformedARGB32PM<BlendTransformedTiled>, // RGB32 + fetchTransformed<BlendTransformedTiled>, // ARGB32 + fetchTransformedARGB32PM<BlendTransformedTiled>, // ARGB32_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB16 + fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB666 + fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB555 + fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied + fetchTransformed<BlendTransformedTiled>, // RGB888 + fetchTransformed<BlendTransformedTiled>, // RGB444 + fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied }, { 0, // Bilinear - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444 - fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear>, // Mono + fetchTransformedBilinear<BlendTransformedBilinear>, // MonoLsb + fetchTransformedBilinear<BlendTransformedBilinear>, // Indexed8 + fetchTransformedBilinearARGB32PM<BlendTransformedBilinear>, // RGB32 + fetchTransformedBilinear<BlendTransformedBilinear>, // ARGB32 + fetchTransformedBilinearARGB32PM<BlendTransformedBilinear>, // ARGB32_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear>, // RGB16 + fetchTransformedBilinear<BlendTransformedBilinear>, // ARGB8565_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear>, // RGB666 + fetchTransformedBilinear<BlendTransformedBilinear>, // ARGB6666_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear>, // RGB555 + fetchTransformedBilinear<BlendTransformedBilinear>, // ARGB8555_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinear>, // RGB888 + fetchTransformedBilinear<BlendTransformedBilinear>, // RGB444 + fetchTransformedBilinear<BlendTransformedBilinear> // ARGB4444_Premultiplied }, { 0, // BilinearTiled - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444 - fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // Mono + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // MonoLsb + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // Indexed8 + fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled>, // RGB32 + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // ARGB32 + fetchTransformedBilinearARGB32PM<BlendTransformedBilinearTiled>, // ARGB32_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB16 + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // ARGB8565_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB666 + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // ARGB6666_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB555 + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // ARGB8555_Premultiplied + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB888 + fetchTransformedBilinear<BlendTransformedBilinearTiled>, // RGB444 + fetchTransformedBilinear<BlendTransformedBilinearTiled> // ARGB4444_Premultiplied }, }; @@ -3274,26 +3722,6 @@ static inline Operator getOperator(const QSpanData *data, const QSpan *spans, in // -------------------- blend methods --------------------- -enum SpanMethod { - RegularSpans, - CallbackSpans -}; - -#if !defined(Q_CC_SUN) -static -#endif -void drawBufferSpan(QSpanData *data, const uint *buffer, int bufsize, - int x, int y, int length, uint const_alpha) -{ - Q_UNUSED(data); - Q_UNUSED(buffer); - Q_UNUSED(bufsize); - Q_UNUSED(x); - Q_UNUSED(y); - Q_UNUSED(length); - Q_UNUSED(const_alpha); -} - #if !defined(Q_CC_SUN) static #endif @@ -3349,55 +3777,6 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) } } -template <class T> -Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - Operator op = getOperator(data, spans, count); - - if (op.mode == QPainter::CompositionMode_Source) { - const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(data->solid.color), 0); - while (count--) { - T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) - + spans->x; - if (spans->coverage == 255) { - qt_memfill(target, c, spans->len); - } else { - const quint8 alpha = T::alpha(spans->coverage); - const T color = c.byte_mul(alpha); - const int ialpha = T::ialpha(spans->coverage); - const T *end = target + spans->len; - while (target < end) { - *target = color + target->byte_mul(ialpha); - ++target; - } - } - ++spans; - } - return; - } - - if (op.mode == QPainter::CompositionMode_SourceOver) { - while (count--) { - const quint32 color = BYTE_MUL(data->solid.color, spans->coverage); - const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0); - const quint8 ialpha = T::alpha(qAlpha(~color)); - T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) + spans->x; - const T *end = target + spans->len; - while (target != end) { - *target = c + target->byte_mul(ialpha); - ++target; - } - ++spans; - } - return; - } - - blend_color_generic(count, spans, userData); -} - -#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST> - static void blend_color_rgb16(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -3542,7 +3921,6 @@ struct QBlendBase uint src_buffer[buffer_size]; }; -template <SpanMethod spanMethod> class BlendSrcGeneric : public QBlendBase { public: @@ -3553,38 +3931,30 @@ public: const uint *fetch(int x, int y, int len) { - if (spanMethod == RegularSpans) - dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer; - + 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); } - void process(int x, int y, int len, int coverage, const uint *src, int offset) + void process(int, int, int len, int coverage, const uint *src, int offset) { - if (spanMethod == RegularSpans) - op.func(dest + offset, src + offset, len, coverage); - else - drawBufferSpan(data, src + offset, len, x, y, len, coverage); + op.func(dest + offset, src + offset, len, coverage); } void store(int x, int y, int len) { - if (spanMethod == RegularSpans && op.dest_store) { + if (op.dest_store) op.dest_store(data->rasterBuffer, x, y, dest, len); - } } }; -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData) +static void blend_src_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); - BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count)); + BlendSrcGeneric blend(data, getOperator(data, spans, count)); handleSpans(count, spans, data, blend); } -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData) +static void blend_untransformed_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -3615,15 +3985,10 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSp while (length) { int l = qMin(buffer_size, length); const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - if (spanMethod == RegularSpans) { - uint *dest = op.dest_fetch ? op.dest_fetch(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); - } else { - drawBufferSpan(data, src, l, x, spans->y, - l, coverage); - } + uint *dest = op.dest_fetch ? op.dest_fetch(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); x += l; sx += l; length -= l; @@ -3634,13 +3999,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSp } } -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData) +static void blend_untransformed_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_untransformed_generic<spanMethod>(count, spans, userData); + blend_untransformed_generic(count, spans, userData); return; } @@ -3667,13 +4031,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan if (length > 0) { const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; const uint *src = (uint *)data->texture.scanLine(sy) + sx; - if (spanMethod == RegularSpans) { - uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; - op.func(dest, src, length, coverage); - } else { - drawBufferSpan(data, src, length, x, - spans->y, length, coverage); - } + uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; + op.func(dest, src, length, coverage); } } ++spans; @@ -3731,1167 +4090,19 @@ static inline void blend_sourceOver_rgb16_rgb16(quint16 *dest, } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void madd_2(DST *dest, const quint16 alpha, const SRC *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - dest[0] = dest[0].byte_mul(alpha >> 8) + DST(src[0]); - dest[1] = dest[1].byte_mul(alpha & 0xff) + DST(src[1]); -} - -template <class DST, class SRC> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void madd_4(DST *dest, const quint32 alpha, const SRC *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - dest[0] = dest[0].byte_mul(alpha >> 24) + DST(src[0]); - dest[1] = dest[1].byte_mul((alpha >> 16) & 0xff) + DST(src[1]); - dest[2] = dest[2].byte_mul((alpha >> 8) & 0xff) + DST(src[2]); - dest[3] = dest[3].byte_mul(alpha & 0xff) + DST(src[3]); -} - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void madd_4(qargb8565 *dest, const quint32 a, const qargb8565 *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - quint32 x, y, t; - quint8 a8; - - { - x = dest32[0]; - y = src32[0]; - - a8 = a >> 24; - - // a0,g0 - t = ((((x & 0x0007e0ff) * a8) >> 5) & 0x0007e0ff) + (y & 0x0007c0f8); - - // r0,b0 - t |= ((((x & 0x00f81f00) * a8) >> 5) & 0x00f81f00) + (y & 0x00f81f00); - - a8 = (a >> 16) & 0xff; - - // a1 - t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); - - dest32[0] = t; - } - { - x = dest32[1]; - y = src32[1]; - - // r1,b1 - t = ((((x & 0x0000f81f) * a8) >> 5) & 0x0000f81f) + (y & 0x0000f81f); - - // g1 - t |= ((((x & 0x000007e0) * a8) >> 5) & 0x000007e0) + (y & 0x000007c0); - - a8 = (a >> 8) & 0xff; - - // a2 - t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); - - { - // rgb2 - quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); - quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); - quint16 t16; - - t16 = ((((x16 & 0xf81f) * a8) >> 5) & 0xf81f) + (y16 & 0xf81f); - t16 |= ((((x16 & 0x07e0) * a8) >> 5) & 0x07e0) + (y16 & 0x07c0); - - // rg2 - t |= ((t16 & 0x00ff) << 24); - - dest32[1] = t; - - x = dest32[2]; - y = src32[2]; - - // gb2 - t = (t16 >> 8); - } - } - { - a8 = a & 0xff; - - // g3,a3 - t |= ((((x & 0x07e0ff00) * a8) >> 5) & 0x07e0ff00) + (y & 0x07c0f800); - - // r3,b3 - t |= ((((x & 0xf81f0000) >> 5) * a8) & 0xf81f0000)+ (y & 0xf81f0000); - - dest32[2] = t; - } -} -#endif - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void madd_4(qargb8555 *dest, const quint32 a, const qargb8555 *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - quint32 x, y, t; - quint8 a8; - - { - x = dest32[0]; - y = src32[0]; - - a8 = a >> 24; - - // a0,g0 - t = ((((x & 0x0003e0ff) * a8) >> 5) & 0x0003e0ff) + (y & 0x0003e0f8); - - // r0,b0 - t |= ((((x & 0x007c1f00) * a8) >> 5) & 0x007c1f00) + (y & 0x007c1f00); - - a8 = (a >> 16) & 0xff; - - // a1 - t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); - - dest32[0] = t; - } - { - x = dest32[1]; - y = src32[1]; - - // r1,b1 - t = ((((x & 0x00007c1f) * a8) >> 5) & 0x00007c1f) + (y & 0x00007c1f); - - // g1 - t |= ((((x & 0x000003e0) * a8) >> 5) & 0x000003e0) + (y & 0x000003e0); - - a8 = (a >> 8) & 0xff; - - // a2 - t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); - - { - // rgb2 - quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); - quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); - quint16 t16; - - t16 = ((((x16 & 0x7c1f) * a8) >> 5) & 0x7c1f) + (y16 & 0x7c1f); - t16 |= ((((x16 & 0x03e0) * a8) >> 5) & 0x03e0) + (y16 & 0x03e0); - - // rg2 - t |= ((t16 & 0x00ff) << 24); - - dest32[1] = t; - - x = dest32[2]; - y = src32[2]; - - // gb2 - t = (t16 >> 8); - } - } - { - a8 = a & 0xff; - - // g3,a3 - t |= ((((x & 0x03e0ff00) * a8) >> 5) & 0x03e0ff00) + (y & 0x03e0f800); - - // r3,b3 - t |= ((((x & 0x7c1f0000) >> 5) * a8) & 0x7c1f0000)+ (y & 0x7c1f0000); - - dest32[2] = t; - } -} -#endif - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 alpha_2(const T *src) -{ - Q_ASSERT((quintptr(src) & 0x3) == 0); - - if (T::hasAlpha()) - return (src[0].alpha() << 8) | src[1].alpha(); - else - return 0xffff; -} - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 alpha_4(const T *src) -{ - Q_ASSERT((quintptr(src) & 0x3) == 0); - - if (T::hasAlpha()) { - return (src[0].alpha() << 24) | (src[1].alpha() << 16) - | (src[2].alpha() << 8) | src[3].alpha(); - } else { - return 0xffffffff; - } -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 alpha_4(const qargb8565 *src) -{ - const quint8 *src8 = reinterpret_cast<const quint8*>(src); - return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 alpha_4(const qargb6666 *src) -{ - const quint8 *src8 = reinterpret_cast<const quint8*>(src); - return ((src8[2] & 0xfc) | (src8[2] >> 6)) << 24 - | ((src8[5] & 0xfc) | (src8[5] >> 6)) << 16 - | ((src8[8] & 0xfc) | (src8[8] >> 6)) << 8 - | ((src8[11] & 0xfc) | (src8[11] >> 6)); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 alpha_4(const qargb8555 *src) -{ - Q_ASSERT((quintptr(src) & 0x3) == 0); - const quint8 *src8 = reinterpret_cast<const quint8*>(src); - return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 alpha_2(const qargb4444 *src) -{ - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - const quint32 t = (*src32 & 0xf000f000) | - ((*src32 & 0xf000f000) >> 4); - return (t >> 24) | (t & 0xff00); -} - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_alpha_2(quint16 alpha, const T*) -{ - return (T::alpha((alpha >> 8) & 0xff) << 8) - | T::alpha(alpha & 0xff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_alpha_2(quint16 a, const qrgb565*) -{ - return ((((a & 0xff00) + 0x0100) >> 3) & 0xff00) - | ((((a & 0x00ff) + 0x0001) >> 3) & 0x00ff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_alpha_2(quint16 a, const qrgb444*) -{ - return (((a & 0x00ff) + 0x0001) >> 4) - | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_alpha_2(quint16 a, const qargb4444*) -{ - return (((a & 0x00ff) + 0x0001) >> 4) - | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); -} - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_ialpha_2(quint16 alpha, const T*) -{ - return (T::ialpha((alpha >> 8) & 0xff) << 8) - | T::ialpha(alpha & 0xff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_ialpha_2(quint16 a, const qrgb565 *dummy) -{ - return 0x2020 - eff_alpha_2(a, dummy); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_ialpha_2(quint16 a, const qargb4444 *dummy) -{ - return 0x1010 - eff_alpha_2(a, dummy); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint16 eff_ialpha_2(quint16 a, const qrgb444 *dummy) -{ - return 0x1010 - eff_alpha_2(a, dummy); -} - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 alpha, const T*) -{ - return (T::alpha(alpha >> 24) << 24) - | (T::alpha((alpha >> 16) & 0xff) << 16) - | (T::alpha((alpha >> 8) & 0xff) << 8) - | T::alpha(alpha & 0xff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 a, const qrgb888*) -{ - return a; -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 a, const qargb8565*) -{ - return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) - | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 a, const qargb6666*) -{ - return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) - | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 a, const qrgb666*) -{ - return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) - | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_alpha_4(quint32 a, const qargb8555*) -{ - return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) - | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); -} - -template <class T> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 alpha, const T*) -{ - return (T::ialpha(alpha >> 24) << 24) - | (T::ialpha((alpha >> 16) & 0xff) << 16) - | (T::ialpha((alpha >> 8) & 0xff) << 8) - | T::ialpha(alpha & 0xff); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 a, const qrgb888*) -{ - return ~a; -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 a, const qargb8565 *dummy) -{ - return 0x20202020 - eff_alpha_4(a, dummy); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 a, const qargb6666 *dummy) -{ - return 0x40404040 - eff_alpha_4(a, dummy); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 a, const qrgb666 *dummy) -{ - return 0x40404040 - eff_alpha_4(a, dummy); -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline quint32 eff_ialpha_4(quint32 a, const qargb8555 *dummy) -{ - return 0x20202020 - eff_alpha_4(a, dummy); -} - -template <class DST, class SRC> -inline void interpolate_pixel_unaligned_2(DST *dest, const SRC *src, - quint16 alpha) -{ - const quint16 a = eff_alpha_2(alpha, dest); - const quint16 ia = eff_ialpha_2(alpha, dest); - dest[0] = DST(src[0]).byte_mul(a >> 8) + dest[0].byte_mul(ia >> 8); - dest[1] = DST(src[1]).byte_mul(a & 0xff) + dest[1].byte_mul(ia & 0xff); -} - -template <class DST, class SRC> -inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint16 a = eff_alpha_2(alpha, dest); - const quint16 ia = eff_ialpha_2(alpha, dest); - - dest[0] = DST(src[0]).byte_mul(a >> 8) + dest[0].byte_mul(ia >> 8); - dest[1] = DST(src[1]).byte_mul(a & 0xff) + dest[1].byte_mul(ia & 0xff); -} - -template <class DST, class SRC> -inline void interpolate_pixel(DST &dest, quint8 a, const SRC &src, quint8 b) -{ - if (SRC::hasAlpha() && !DST::hasAlpha()) - interpolate_pixel(dest, a, DST(src), b); - else - dest = dest.byte_mul(a) + DST(src).byte_mul(b); -} - -template <> -inline void interpolate_pixel(qargb8565 &dest, quint8 a, - const qargb8565 &src, quint8 b) -{ - quint8 *d = reinterpret_cast<quint8*>(&dest); - const quint8 *s = reinterpret_cast<const quint8*>(&src); - d[0] = (d[0] * a + s[0] * b) >> 5; - - const quint16 x = (d[2] << 8) | d[1]; - const quint16 y = (s[2] << 8) | s[1]; - quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; - t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; - - d[1] = t & 0xff; - d[2] = t >> 8; -} - -template <> -inline void interpolate_pixel(qrgb565 &dest, quint8 a, - const qrgb565 &src, quint8 b) -{ - const quint16 x = dest.rawValue(); - const quint16 y = src.rawValue(); - quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; - t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; - dest = t; -} - -template <> -inline void interpolate_pixel(qrgb555 &dest, quint8 a, - const qrgb555 &src, quint8 b) -{ - const quint16 x = dest.rawValue(); - const quint16 y = src.rawValue(); - quint16 t = (((x & 0x03e0) * a + (y & 0x03e0) * b) >> 5) & 0x03e0; - t |= ((((x & 0x7c1f) * a) + ((y & 0x7c1f) * b)) >> 5) & 0x7c1f; - dest = t; -} - -template <> -inline void interpolate_pixel(qrgb444 &dest, quint8 a, - const qrgb444 &src, quint8 b) -{ - const quint16 x = dest.rawValue(); - const quint16 y = src.rawValue(); - quint16 t = ((x & 0x00f0) * a + (y & 0x00f0) * b) & 0x0f00; - t |= ((x & 0x0f0f) * a + (y & 0x0f0f) * b) & 0xf0f0; - quint16 *d = reinterpret_cast<quint16*>(&dest); - *d = (t >> 4); -} - -template <class DST, class SRC> -inline void interpolate_pixel_2(DST *dest, quint8 a, - const SRC *src, quint8 b) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - Q_ASSERT(!SRC::hasAlpha()); - - dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b); - dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b); -} - -template <> -inline void interpolate_pixel_2(qrgb565 *dest, quint8 a, - const qrgb565 *src, quint8 b) -{ - quint32 *x = reinterpret_cast<quint32*>(dest); - const quint32 *y = reinterpret_cast<const quint32*>(src); - quint32 t = (((*x & 0xf81f07e0) >> 5) * a + - ((*y & 0xf81f07e0) >> 5) * b) & 0xf81f07e0; - t |= (((*x & 0x07e0f81f) * a - + (*y & 0x07e0f81f) * b) >> 5) & 0x07e0f81f; - *x = t; -} - -template <> -inline void interpolate_pixel_2(qrgb555 *dest, quint8 a, - const qrgb555 *src, quint8 b) -{ - quint32 *x = reinterpret_cast<quint32*>(dest); - const quint32 *y = reinterpret_cast<const quint32*>(src); - quint32 t = (((*x & 0x7c1f03e0) >> 5) * a + - ((*y & 0x7c1f03e0) >> 5) * b) & 0x7c1f03e0; - t |= (((*x & 0x03e07c1f) * a - + (*y & 0x03e07c1f) * b) >> 5) & 0x03e07c1f; - *x = t; -} - -template <> -inline void interpolate_pixel_2(qrgb444 *dest, quint8 a, - const qrgb444 *src, quint8 b) -{ - quint32 *x = reinterpret_cast<quint32*>(dest); - const quint32 *y = reinterpret_cast<const quint32*>(src); - quint32 t = ((*x & 0x0f0f0f0f) * a + (*y & 0x0f0f0f0f) * b) & 0xf0f0f0f0; - t |= ((*x & 0x00f000f0) * a + (*y & 0x00f000f0) * b) & 0x0f000f00; - *x = t >> 4; -} - -template <class DST, class SRC> -inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = eff_alpha_4(alpha, dest); - const quint32 ia = eff_ialpha_4(alpha, dest); - dest[0] = DST(src[0]).byte_mul(a >> 24) - + dest[0].byte_mul(ia >> 24); - dest[1] = DST(src[1]).byte_mul((a >> 16) & 0xff) - + dest[1].byte_mul((ia >> 16) & 0xff); - dest[2] = DST(src[2]).byte_mul((a >> 8) & 0xff) - + dest[2].byte_mul((ia >> 8) & 0xff); - dest[3] = DST(src[3]).byte_mul(a & 0xff) - + dest[3].byte_mul(ia & 0xff); -} - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -template <> -inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src, - quint32 alpha) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = eff_alpha_4(alpha, dest); - const quint32 ia = eff_ialpha_4(alpha, dest); - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - - quint32 x, y, t; - quint8 a8, ia8; - { - x = src32[0]; - y = dest32[0]; - - a8 = a >> 24; - ia8 = ia >> 24; - - // a0,g0 - t = (((x & 0x0007e0ff) * a8 + (y & 0x0007e0ff) * ia8) >> 5) - & 0x0007e0ff; - - // r0,b0 - t |= (((x & 0x00f81f00) * a8 + (y & 0x00f81f00) * ia8) >> 5) - & 0x00f81f00; - - a8 = (a >> 16) & 0xff; - ia8 = (ia >> 16) & 0xff; - - // a1 - t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) - & 0xff000000; - - dest32[0] = t; - } - { - x = src32[1]; - y = dest32[1]; - - // r1,b1 - t = (((x & 0x0000f81f) * a8 + (y & 0x0000f81f) * ia8) >> 5) - & 0x0000f81f; - - // g1 - t |= (((x & 0x000007e0) * a8 + (y & 0x000007e0) * ia8) >> 5) - & 0x000007e0; - - a8 = (a >> 8) & 0xff; - ia8 = (ia >> 8) & 0xff; - - // a2 - t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) - & 0x00ff0000; - - { - // rgb2 - quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); - quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); - quint16 t16; - - t16 = (((x16 & 0xf81f) * a8 + (y16 & 0xf81f) * ia8) >> 5) & 0xf81f; - t16 |= (((x16 & 0x07e0) * a8 + (y16 & 0x07e0) * ia8) >> 5) & 0x07e0; - - // rg2 - t |= ((t16 & 0x00ff) << 24); - - dest32[1] = t; - - x = src32[2]; - y = dest32[2]; - - // gb2 - t = (t16 >> 8); - } - } - { - a8 = a & 0xff; - ia8 = ia & 0xff; - - // g3,a3 - t |= (((x & 0x07e0ff00) * a8 + (y & 0x07e0ff00) * ia8) >> 5) - & 0x07e0ff00; - - // r3,b3 - t |= (((x & 0xf81f0000) >> 5) * a8 + ((y & 0xf81f0000) >> 5) * ia8) - & 0xf81f0000; - - dest32[2] = t; - } -} -#endif - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -template <> -inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src, - quint32 alpha) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - - const quint32 a = eff_alpha_4(alpha, dest); - const quint32 ia = eff_ialpha_4(alpha, dest); - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - - quint32 x, y, t; - quint8 a8, ia8; - { - x = src32[0]; - y = dest32[0]; - - a8 = a >> 24; - ia8 = ia >> 24; - - // a0,g0 - t = (((x & 0x0003e0ff) * a8 + (y & 0x0003e0ff) * ia8) >> 5) - & 0x0003e0ff; - - // r0,b0 - t |= (((x & 0x007c1f00) * a8 + (y & 0x007c1f00) * ia8) >> 5) - & 0x007c1f00; - - a8 = (a >> 16) & 0xff; - ia8 = (ia >> 16) & 0xff; - - // a1 - t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) - & 0xff000000; - - dest32[0] = t; - } - { - x = src32[1]; - y = dest32[1]; - - // r1,b1 - t = (((x & 0x00007c1f) * a8 + (y & 0x00007c1f) * ia8) >> 5) - & 0x00007c1f; - - // g1 - t |= (((x & 0x000003e0) * a8 + (y & 0x000003e0) * ia8) >> 5) - & 0x000003e0; - - a8 = (a >> 8) & 0xff; - ia8 = (ia >> 8) & 0xff; - - // a2 - t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) - & 0x00ff0000; - - { - // rgb2 - quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); - quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); - quint16 t16; - - t16 = (((x16 & 0x7c1f) * a8 + (y16 & 0x7c1f) * ia8) >> 5) & 0x7c1f; - t16 |= (((x16 & 0x03e0) * a8 + (y16 & 0x03e0) * ia8) >> 5) & 0x03e0; - - // rg2 - t |= ((t16 & 0x00ff) << 24); - - dest32[1] = t; - - x = src32[2]; - y = dest32[2]; - - // gb2 - t = (t16 >> 8); - } - } - { - a8 = a & 0xff; - ia8 = ia & 0xff; - - // g3,a3 - t |= (((x & 0x03e0ff00) * a8 + (y & 0x03e0ff00) * ia8) >> 5) - & 0x03e0ff00; - - // r3,b3 - t |= (((x & 0x7c1f0000) >> 5) * a8 + ((y & 0x7c1f0000) >> 5) * ia8) - & 0x7c1f0000; - - dest32[2] = t; - } -} -#endif - -template <> -inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src, - quint32 alpha) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = eff_alpha_4(alpha, dest); - const quint32 ia = eff_ialpha_4(alpha, dest); - const quint32 *src32 = reinterpret_cast<const quint32*>(src); - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - - { - quint32 x = src32[0]; - quint32 y = dest32[0]; - - quint32 t; - t = ((x >> 8) & 0xff00ff) * (a >> 24) - + ((y >> 8) & 0xff00ff) * (ia >> 24); - t = (t + ((t >> 8) & 0xff00ff) + 0x800080); - t &= 0xff00ff00; - - x = (x & 0xff0000) * (a >> 24) - + (x & 0x0000ff) * ((a >> 16) & 0xff) - + (y & 0xff0000) * (ia >> 24) - + (y & 0x0000ff) * ((ia >> 16) & 0xff); - x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; - x &= 0x00ff00ff; - - dest32[0] = x | t; - } - { - quint32 x = src32[1]; - quint32 y = dest32[1]; - - quint32 t; - t = ((x >> 8) & 0xff0000) * ((a >> 16) & 0xff) - + ((x >> 8) & 0x0000ff) * ((a >> 8) & 0xff) - + ((y >> 8) & 0xff0000) * ((ia >> 16) & 0xff) - + ((y >> 8) & 0x0000ff) * ((ia >> 8) & 0xff); - t = (t + ((t >> 8) & 0xff00ff) + 0x800080); - t &= 0xff00ff00; - - x = (x & 0xff0000) * ((a >> 16) & 0xff) - + (x & 0x0000ff) * ((a >> 8) & 0xff) - + (y & 0xff0000) * ((ia >> 16) & 0xff) - + (y & 0x0000ff) * ((ia >> 8) & 0xff); - x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; - x &= 0x00ff00ff; - - dest32[1] = x | t; - } - { - quint32 x = src32[2]; - quint32 y = dest32[2]; - - quint32 t; - t = ((x >> 8) & 0xff0000) * ((a >> 8) & 0xff) - + ((x >> 8) & 0x0000ff) * (a & 0xff) - + ((y >> 8) & 0xff0000) * ((ia >> 8) & 0xff) - + ((y >> 8) & 0x0000ff) * (ia & 0xff); - t = (t + ((t >> 8) & 0xff00ff) + 0x800080); - t &= 0xff00ff00; - - x = (x & 0xff00ff) * (a & 0xff) - + (y & 0xff00ff) * (ia & 0xff); - x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; - x &= 0x00ff00ff; - - dest32[2] = x | t; - } -} - -template <class DST, class SRC> -inline void interpolate_pixel_4(DST *dest, quint8 a, - const SRC *src, quint8 b) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b); - dest[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b); - dest[2] = dest[2].byte_mul(a) + DST(src[2]).byte_mul(b); - dest[3] = dest[3].byte_mul(a) + DST(src[3]).byte_mul(b); -} - -template <class DST, class SRC> -inline void blend_sourceOver_4(DST *dest, const SRC *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = alpha_4(src); - if (a == 0xffffffff) { - qt_memconvert(dest, src, 4); - } else if (a > 0) { - quint32 buf[3]; // array of quint32 to get correct alignment - qt_memconvert((DST*)(void*)buf, src, 4); - madd_4(dest, eff_ialpha_4(a, dest), (DST*)(void*)buf); - } -} - -template <> -inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = alpha_4(src); - if (a == 0xffffffff) { - qt_memconvert(dest, src, 4); - } else if (a > 0) { - madd_4(dest, eff_ialpha_4(a, dest), src); - } -} - -template <> -inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = alpha_4(src); - if (a == 0xffffffff) { - qt_memconvert(dest, src, 4); - } else if (a > 0) { - madd_4(dest, eff_ialpha_4(a, dest), src); - } -} - -template <> -inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src) -{ - Q_ASSERT((quintptr(dest) & 0x3) == 0); - Q_ASSERT((quintptr(src) & 0x3) == 0); - - const quint32 a = alpha_4(src); - if (a == 0xffffffff) { - qt_memconvert(dest, src, 4); - } else if (a > 0) { - madd_4(dest, eff_ialpha_4(a, dest), src); - } -} - -template <class DST, class SRC> -void QT_FASTCALL blendUntransformed_unaligned(DST *dest, const SRC *src, - quint8 coverage, int length) -{ - Q_ASSERT(coverage > 0); - - if (coverage < 255) { - if (SRC::hasAlpha()) { - for (int i = 0; i < length; ++i) { - if (src[i].alpha()) { - const quint8 alpha = qt_div_255(int(src[i].alpha()) * int(coverage)); - interpolate_pixel(dest[i], DST::ialpha(alpha), - src[i], DST::alpha(alpha)); - } - } - } else { - const quint8 alpha = DST::alpha(coverage); - const quint8 ialpha = DST::ialpha(coverage); - if (alpha) { - for (int i = 0; i < length; ++i) - interpolate_pixel(dest[i], ialpha, src[i], alpha); - } - } - return; - } - - Q_ASSERT(coverage == 0xff); - Q_ASSERT(SRC::hasAlpha()); - - if (SRC::hasAlpha()) { - for (int i = 0; i < length; ++i) { - const quint8 a = src->alpha(); - if (a == 0xff) - *dest = DST(*src); - else if (a > 0) { - if (DST::hasAlpha()) - *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); - else - *dest = DST(SRC(*src).truncedAlpha()) + dest->byte_mul(DST::ialpha(a)); - } - ++src; - ++dest; - } - } -} - -template <class DST, class SRC> -void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src, - quint8 coverage, int length) -{ - Q_ASSERT(sizeof(DST) == 2); - Q_ASSERT(sizeof(SRC) == 2); - Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); - Q_ASSERT(coverage > 0); - - const int align = quintptr(dest) & 0x3; - - if (coverage < 255) { - // align - if (align) { - const quint8 alpha = SRC::hasAlpha() - ? qt_div_255(int(src->alpha()) * int(coverage)) - : coverage; - if (alpha) { - interpolate_pixel(*dest, DST::ialpha(alpha), - *src, DST::alpha(alpha)); - } - ++dest; - ++src; - --length; - } - - if (SRC::hasAlpha()) { - while (length >= 2) { - const quint16 alpha16 = BYTE_MUL(uint(alpha_2(src)), uint(coverage)); - interpolate_pixel_2(dest, src, alpha16); - length -= 2; - src += 2; - dest += 2; - } - } else { - const quint8 alpha = DST::alpha(coverage); - const quint8 ialpha = DST::ialpha(coverage); - - while (length >= 2) { - interpolate_pixel_2(dest, ialpha, src, alpha); - length -= 2; - src += 2; - dest += 2; - } - } - - // tail - if (length) { - const quint8 alpha = SRC::hasAlpha() - ? qt_div_255(int(src->alpha()) * int(coverage)) - : coverage; - if (alpha) { - interpolate_pixel(*dest, DST::ialpha(alpha), - *src, DST::alpha(alpha)); - } - } - - return; - } - - Q_ASSERT(SRC::hasAlpha()); - if (SRC::hasAlpha()) { - if (align) { - const quint8 alpha = src->alpha(); - if (alpha == 0xff) - *dest = DST(*src); - else if (alpha > 0) - *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); - ++dest; - ++src; - --length; - } - - while (length >= 2) { - Q_ASSERT((quintptr(dest) & 3) == 0); - Q_ASSERT((quintptr(src) & 3) == 0); - - const quint16 a = alpha_2(src); - if (a == 0xffff) { - qt_memconvert(dest, src, 2); - } else if (a > 0) { - quint32 buf; - if (sizeof(DST) == 2) - qt_memconvert((DST*)(void*)&buf, src, 2); - madd_2(dest, eff_ialpha_2(a, dest), (DST*)(void*)&buf); - } - - length -= 2; - src += 2; - dest += 2; - } - - if (length) { - const quint8 alpha = src->alpha(); - if (alpha == 0xff) - *dest = DST(*src); - else if (alpha > 0) - *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); - } - } -} - -template <class DST, class SRC> -void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src, - quint8 coverage, int length) -{ - Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); - Q_ASSERT(sizeof(DST) == 3); - Q_ASSERT(coverage > 0); - - const int align = quintptr(dest) & 0x3; - - if (coverage < 255) { - // align - for (int i = 0; i < align; ++i) { - if (SRC::hasAlpha()) { - const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); - if (alpha) - interpolate_pixel(*dest, DST::ialpha(alpha), - *src, DST::alpha(alpha)); - } else { - interpolate_pixel(*dest, DST::ialpha(coverage), - *src, DST::alpha(coverage)); - } - ++dest; - ++src; - --length; - } - - if (SRC::hasAlpha()) { - while (length >= 4) { - const quint32 alpha = QT_PREPEND_NAMESPACE(BYTE_MUL)(uint(alpha_4(src)), uint(coverage)); - if (alpha) - interpolate_pixel_4(dest, src, alpha); - length -= 4; - src += 4; - dest += 4; - } - } else { - const quint8 alpha = DST::alpha(coverage); - const quint8 ialpha = DST::ialpha(coverage); - while (length >= 4) { - interpolate_pixel_4(dest, ialpha, src, alpha); - length -= 4; - src += 4; - dest += 4; - } - } - - // tail - while (length--) { - if (SRC::hasAlpha()) { - const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); - if (alpha) - interpolate_pixel(*dest, DST::ialpha(alpha), - *src, DST::alpha(alpha)); - } else { - interpolate_pixel(*dest, DST::ialpha(coverage), - *src, DST::alpha(coverage)); - } - ++dest; - ++src; - } - - return; - } - - - Q_ASSERT(coverage == 255); - Q_ASSERT(SRC::hasAlpha()); - - if (SRC::hasAlpha()) { - // align - for (int i = 0; i < align; ++i) { - const quint8 a = src->alpha(); - if (a == 0xff) { - *dest = DST(*src); - } else if (a > 0) { - *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); - } - ++dest; - ++src; - --length; - } - - while (length >= 4) { - blend_sourceOver_4(dest, src); - length -= 4; - src += 4; - dest += 4; - } - - // tail - while (length--) { - const quint8 a = src->alpha(); - if (a == 0xff) { - *dest = DST(*src); - } else if (a > 0) { - *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); - } - ++dest; - ++src; - } - } -} - -template <class DST, class SRC> -Q_STATIC_TEMPLATE_SPECIALIZATION -void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userData) +static void blend_untransformed_rgb565(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData*>(userData); QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode != QPainter::CompositionMode_SourceOver && - mode != QPainter::CompositionMode_Source) + if (data->texture.format != QImage::Format_RGB16 + || (mode != QPainter::CompositionMode_SourceOver + && mode != QPainter::CompositionMode_Source)) { - blend_src_generic<RegularSpans>(count, spans, userData); + blend_untransformed_generic(count, spans, userData); return; } - const bool modeSource = !SRC::hasAlpha() || - mode == QPainter::CompositionMode_Source; const int image_width = data->texture.width; const int image_height = data->texture.height; int xoff = -qRound(-data->dx); @@ -4917,20 +4128,15 @@ void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userDat if (sx + length > image_width) length = image_width - sx; if (length > 0) { - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - if (modeSource && coverage == 255) { - qt_memconvert<DST, SRC>(dest, src, length); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && length >= 3 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest24(dest, src, coverage, length); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && length >= 3 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest16(dest, src, coverage, length); + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + x; + const quint16 *src = (quint16 *)data->texture.scanLine(sy) + sx; + if (coverage == 255) { + memcpy(dest, src, length * sizeof(quint16)); } else { - blendUntransformed_unaligned(dest, src, coverage, length); + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha > 0) + blend_sourceOver_rgb16_rgb16(dest, src, length, alpha, ialpha); } } } @@ -4938,69 +4144,7 @@ void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userDat } } -static void blend_untransformed_rgb888(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_argb6666(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_rgb666(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_argb8565(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_rgb565(int count, const QSpan *spans, - void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) - blendUntransformed<qrgb565, qargb8565>(count, spans, userData); - else if (data->texture.format == QImage::Format_RGB16) - blendUntransformed<qrgb565, qrgb565>(count, spans, userData); - else - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_argb8555(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_rgb555(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_argb4444(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -static void blend_untransformed_rgb444(int count, const QSpan *spans, - void *userData) -{ - blend_untransformed_generic<RegularSpans>(count, spans, userData); -} - -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData) +static void blend_tiled_generic(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); @@ -5034,15 +4178,10 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *span if (buffer_size < l) l = buffer_size; const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); - if (spanMethod == RegularSpans) { - uint *dest = op.dest_fetch ? op.dest_fetch(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); - } else { - drawBufferSpan(data, src, l, x, spans->y, l, - coverage); - } + uint *dest = op.dest_fetch ? op.dest_fetch(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); x += l; sx += l; length -= l; @@ -5053,13 +4192,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *span } } -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData) +static void blend_tiled_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_tiled_generic<spanMethod>(count, spans, userData); + blend_tiled_generic(count, spans, userData); return; } @@ -5091,13 +4229,8 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, if (buffer_size < l) l = buffer_size; const uint *src = (uint *)data->texture.scanLine(sy) + sx; - if (spanMethod == RegularSpans) { - uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; - op.func(dest, src, l, coverage); - } else { - drawBufferSpan(data, src, buffer_size, - x, spans->y, l, coverage); - } + uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; + op.func(dest, src, l, coverage); x += l; length -= l; sx = 0; @@ -5106,21 +4239,19 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *userData) +static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData*>(userData); QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode != QPainter::CompositionMode_SourceOver && - mode != QPainter::CompositionMode_Source) + if (data->texture.format != QImage::Format_RGB16 + || (mode != QPainter::CompositionMode_SourceOver + && mode != QPainter::CompositionMode_Source)) { - blend_src_generic<RegularSpans>(count, spans, userData); + blend_tiled_generic(count, spans, userData); return; } - const bool modeSource = !SRC::hasAlpha() || - mode == QPainter::CompositionMode_Source; const int image_width = data->texture.width; const int image_height = data->texture.height; int xoff = -qRound(-data->dx) % image_width; @@ -5147,7 +4278,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * if (sy < 0) sy += image_height; - if (modeSource && coverage == 255) { + if (coverage == 255) { // Copy the first texture block length = qMin(image_width,length); int tx = x; @@ -5155,10 +4286,9 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * int l = qMin(image_width - sx, length); if (buffer_size < l) l = buffer_size; - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + tx; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - - qt_memconvert<DST, SRC>(dest, src, l); + quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + tx; + const quint16 *src = (quint16 *)data->texture.scanLine(sy) + sx; + memcpy(dest, src, l * sizeof(quint16)); length -= l; tx += l; sx = 0; @@ -5172,110 +4302,51 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * // - can use memcpy int copy_image_width = qMin(image_width, int(spans->len)); length = spans->len - copy_image_width; - DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - DST *dest = src + copy_image_width; + quint16 *src = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x; + quint16 *dest = src + copy_image_width; while (copy_image_width < length) { - qt_memconvert(dest, src, copy_image_width); + memcpy(dest, src, copy_image_width * sizeof(quint16)); dest += copy_image_width; length -= copy_image_width; copy_image_width *= 2; } if (length > 0) - qt_memconvert(dest, src, length); + memcpy(dest, src, length * sizeof(quint16)); } else { - while (length) { - int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest24(dest, src, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest16(dest, src, coverage, l); - } else { - blendUntransformed_unaligned(dest, src, coverage, l); + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha > 0) { + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + quint16 *dest = ((quint16 *)data->rasterBuffer->scanLine(spans->y)) + x; + const quint16 *src = (quint16 *)data->texture.scanLine(sy) + sx; + blend_sourceOver_rgb16_rgb16(dest, src, l, alpha, ialpha); + x += l; + length -= l; + sx = 0; } - - x += l; - length -= l; - sx = 0; } } ++spans; } } -static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) - blendTiled<qrgb565, qargb8565>(count, spans, userData); - else if (data->texture.format == QImage::Format_RGB16) - blendTiled<qrgb565, qrgb565>(count, spans, userData); - else - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) -{ - blend_tiled_generic<RegularSpans>(count, spans, userData); -} - -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan *spans, - void *userData) +static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData*>(userData); QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - - if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData); + if (data->texture.format != QImage::Format_RGB16 + || (mode != QPainter::CompositionMode_SourceOver + && mode != QPainter::CompositionMode_Source)) + { + blend_src_generic(count, spans, userData); return; } - SRC buffer[buffer_size]; + quint16 buffer[buffer_size]; const int src_minx = data->texture.x1; const int src_miny = data->texture.y1; @@ -5289,13 +4360,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); int x = int((data->m21 * cy @@ -5305,84 +4377,58 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; - const SRC *end = buffer + l; - SRC *b = buffer; while (b < end) { int x1 = (x >> 16); int x2; int y1 = (y >> 16); int y2; - const int distx = (x & 0x0000ffff) >> 8; - const int disty = (y & 0x0000ffff) >> 8; + fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2); + fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2); + + const quint16 *src1 = (quint16*)data->texture.scanLine(y1); + const quint16 *src2 = (quint16*)data->texture.scanLine(y2); + quint16 tl = src1[x1]; + const quint16 tr = src1[x2]; + quint16 bl = src2[x1]; + const quint16 br = src2[x2]; + + const uint distxsl8 = x & 0xff00; + const uint distysl8 = y & 0xff00; + const uint distx = distxsl8 >> 8; + const uint disty = distysl8 >> 8; + const uint distxy = distx * disty; + + const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty) + const uint trw = distxsl8 - distxy; // distx * (256 - disty) + const uint blw = distysl8 - distxy; // (256 - distx) * disty + const uint brw = distxy; // distx * disty + uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw + + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000; + uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw + + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000; + uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw + + (bl & 0x001f) * blw + (br & 0x001f) * brw); + *b = quint16((red | green | blue) >> 16); - if (x1 < src_minx) { - x2 = x1 = src_minx; - } else if (x1 >= src_maxx) { - x2 = x1 = src_maxx; - } else { - x2 = x1 + 1; - } - if (y1 < src_miny) { - y2 = y1 = src_miny; - } else if (y1 >= src_maxy) { - y2 = y1 = src_maxy; - } else { - y2 = y1 + 1; - } -#if 0 - if (x1 == x2) { - if (y1 == y2) { - *b = ((SRC*)data->texture.scanLine(y1))[x1]; - } else { - *b = ((SRC*)data->texture.scanLine(y1))[x1]; - const SRC t = data->texture.scanLine(y2)[x1]; - interpolate_pixel(*b, SRC::ialpha(disty), - t, SRC::alpha(disty)); - } - } else if (y1 == y2) { - *b = ((SRC*)data->texture.scanLine(y1))[x1]; - const SRC t = ((SRC*)data->texture.scanLine(y1))[x2]; - interpolate_pixel(*b, SRC::ialpha(distx), - t, SRC::alpha(distx)); - } else -#endif - { - const SRC *src1 = (SRC*)data->texture.scanLine(y1); - const SRC *src2 = (SRC*)data->texture.scanLine(y2); - SRC tl = src1[x1]; - const SRC tr = src1[x2]; - SRC bl = src2[x1]; - const SRC br = src2[x2]; - const quint8 ax = SRC::alpha(distx); - const quint8 iax = SRC::ialpha(distx); - - interpolate_pixel(tl, iax, tr, ax); - interpolate_pixel(bl, iax, br, ax); - interpolate_pixel(tl, SRC::ialpha(disty), - bl, SRC::alpha(disty)); - *b = tl; - } ++b; - x += fdx; y += fdy; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -5396,13 +4442,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); @@ -5413,9 +4460,17 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); - const SRC *end = buffer + l; - SRC *b = buffer; + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; + while (b < end) { const qreal iw = w == 0 ? 1 : 1 / w; const qreal px = x * iw - qreal(0.5); @@ -5426,56 +4481,42 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan int y1 = int(py) - (py < 0); int y2; - const int distx = int((px - x1) * 256); - const int disty = int((py - y1) * 256); + fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_minx, src_maxx, x1, x2); + fetchTransformedBilinear_pixelBounds<BlendTransformedBilinear>(0, src_miny, src_maxy, y1, y2); + + const quint16 *src1 = (quint16 *)data->texture.scanLine(y1); + const quint16 *src2 = (quint16 *)data->texture.scanLine(y2); + quint16 tl = src1[x1]; + const quint16 tr = src1[x2]; + quint16 bl = src2[x1]; + const quint16 br = src2[x2]; + + const uint distx = uint((px - x1) * 256); + const uint disty = uint((py - y1) * 256); + const uint distxsl8 = distx << 8; + const uint distysl8 = disty << 8; + const uint distxy = distx * disty; + + const uint tlw = 0x10000 - distxsl8 - distysl8 + distxy; // (256 - distx) * (256 - disty) + const uint trw = distxsl8 - distxy; // distx * (256 - disty) + const uint blw = distysl8 - distxy; // (256 - distx) * disty + const uint brw = distxy; // distx * disty + uint red = ((tl & 0xf800) * tlw + (tr & 0xf800) * trw + + (bl & 0xf800) * blw + (br & 0xf800) * brw) & 0xf8000000; + uint green = ((tl & 0x07e0) * tlw + (tr & 0x07e0) * trw + + (bl & 0x07e0) * blw + (br & 0x07e0) * brw) & 0x07e00000; + uint blue = ((tl & 0x001f) * tlw + (tr & 0x001f) * trw + + (bl & 0x001f) * blw + (br & 0x001f) * brw); + *b = quint16((red | green | blue) >> 16); - if (x1 < src_minx) { - x2 = x1 = src_minx; - } else if (x1 >= src_maxx) { - x2 = x1 = src_maxx; - } else { - x2 = x1 + 1; - } - if (y1 < src_miny) { - y2 = y1 = src_miny; - } else if (y1 >= src_maxy) { - y2 = y1 = src_maxy; - } else { - y2 = y1 + 1; - } - - const SRC *src1 = (SRC*)data->texture.scanLine(y1); - const SRC *src2 = (SRC*)data->texture.scanLine(y2); - SRC tl = src1[x1]; - const SRC tr = src1[x2]; - SRC bl = src2[x1]; - const SRC br = src2[x2]; - const quint8 ax = SRC::alpha(distx); - const quint8 iax = SRC::ialpha(distx); - - interpolate_pixel(tl, iax, tr, ax); - interpolate_pixel(bl, iax, br, ax); - interpolate_pixel(tl, SRC::ialpha(disty), - bl, SRC::alpha(disty)); - *b = tl; ++b; - x += fdx; y += fdy; w += fdw; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -5485,66 +4526,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan } } -static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, - void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - if (data->texture.format == QImage::Format_RGB16) - blendTransformedBilinear<qrgb565, qrgb565>(count, spans, userData); - else if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) - blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData); - else - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData) +static void blend_transformed_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData); + blend_src_generic(count, spans, userData); return; } @@ -5553,7 +4540,6 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s int image_width = data->texture.width; int image_height = data->texture.height; - const int scanline_offset = data->texture.bytesPerLine / 4; if (data->fast_matrix) { // The increment pr x in the scanline @@ -5564,7 +4550,6 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s void *t = data->rasterBuffer->scanLine(spans->y); uint *target = ((uint *)t) + spans->x; - uint *image_bits = (uint *)data->texture.imageData; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); @@ -5581,24 +4566,15 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s const uint *end = buffer + l; uint *b = buffer; while (b < end) { - int px = x >> 16; - int py = y >> 16; + int px = qBound(0, x >> 16, image_width - 1); + int py = qBound(0, y >> 16, image_height - 1); + *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; - bool out = (px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height); - - int y_offset = py * scanline_offset; - *b = out ? uint(0) : image_bits[y_offset + px]; x += fdx; y += fdy; ++b; } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); + func(target, buffer, l, coverage); target += l; length -= l; } @@ -5612,7 +4588,6 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s void *t = data->rasterBuffer->scanLine(spans->y); uint *target = ((uint *)t) + spans->x; - uint *image_bits = (uint *)data->texture.imageData; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); @@ -5631,26 +4606,17 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s const qreal iw = w == 0 ? 1 : 1 / w; const qreal tx = x * iw; const qreal ty = y * iw; - const int px = int(tx) - (tx < 0); - const int py = int(ty) - (ty < 0); + const int px = qBound(0, int(tx) - (tx < 0), image_width - 1); + const int py = qBound(0, int(ty) - (ty < 0), image_height - 1); - bool out = (px < 0) || (px >= image_width) - || (py < 0) || (py >= image_height); - - int y_offset = py * scanline_offset; - *b = out ? uint(0) : image_bits[y_offset + px]; + *b = reinterpret_cast<const uint *>(data->texture.scanLine(py))[px]; x += fdx; y += fdy; w += fdw; ++b; } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); + func(target, buffer, l, coverage); target += l; length -= l; } @@ -5659,18 +4625,20 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *s } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, void *userData) +static void blend_transformed_rgb565(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData*>(userData); QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData); + if (data->texture.format != QImage::Format_RGB16 + || (mode != QPainter::CompositionMode_SourceOver + && mode != QPainter::CompositionMode_Source)) + { + blend_src_generic(count, spans, userData); return; } - SRC buffer[buffer_size]; + quint16 buffer[buffer_size]; const int image_width = data->texture.width; const int image_height = data->texture.height; @@ -5681,13 +4649,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); int x = int((data->m21 * cy @@ -5697,39 +4666,30 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; - const SRC *end = buffer + l; - SRC *b = buffer; while (b < end) { - const int px = (x >> 16); - const int py = (y >> 16); + const int px = qBound(0, x >> 16, image_width - 1); + const int py = qBound(0, y >> 16, image_height - 1); - if ((px < 0) || (px >= image_width) || - (py < 0) || (py >= image_height)) - { - *b = 0; - } else { - *b = ((SRC*)data->texture.scanLine(py))[px]; - } + *b = ((quint16 *)data->texture.scanLine(py))[px]; ++b; x += fdx; y += fdy; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -5743,13 +4703,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); @@ -5760,42 +4721,35 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); - const SRC *end = buffer + l; - SRC *b = buffer; + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; + while (b < end) { const qreal iw = w == 0 ? 1 : 1 / w; const qreal tx = x * iw; const qreal ty = y * iw; - const int px = int(tx) - (tx < 0); - const int py = int(ty) - (ty < 0); + const int px = qBound(0, int(tx) - (tx < 0), image_width - 1); + const int py = qBound(0, int(ty) - (ty < 0), image_height - 1); - if ((px < 0) || (px >= image_width) || - (py < 0) || (py >= image_height)) - { - *b = 0; - } else { - *b = ((SRC*)data->texture.scanLine(py))[px]; - } + *b = ((quint16 *)data->texture.scanLine(py))[px]; ++b; x += fdx; y += fdy; w += fdw; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -5805,74 +4759,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, } } -static void blend_transformed_rgb888(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_argb6666(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_rgb666(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_argb8565(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_rgb565(int count, const QSpan *spans, - void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) - blendTransformed<qrgb565, qargb8565>(count, spans, userData); - else if (data->texture.format == QImage::Format_RGB16) - blendTransformed<qrgb565, qrgb565>(count, spans, userData); - else - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_argb8555(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_rgb555(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_argb4444(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_rgb444(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -template <SpanMethod spanMethod> -Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData) +void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format != QImage::Format_ARGB32_Premultiplied && data->texture.format != QImage::Format_RGB32) { - blend_src_generic<spanMethod>(count, spans, userData); + blend_src_generic(count, spans, userData); return; } @@ -5925,12 +4817,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QS y += fdy; ++b; } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); + func(target, buffer, l, coverage); target += l; length -= l; } @@ -5985,12 +4872,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QS } ++b; } - if (spanMethod == RegularSpans) - func(target, buffer, l, coverage); - else - drawBufferSpan(data, buffer, buffer_size, - spans->x + spans->len - length, - spans->y, l, coverage); + func(target, buffer, l, coverage); target += l; length -= l; } @@ -5999,18 +4881,20 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QS } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *spans, void *userData) +void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData*>(userData); QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; - if (mode != QPainter::CompositionMode_SourceOver) { - blend_src_generic<RegularSpans>(count, spans, userData); + if (data->texture.format != QImage::Format_RGB16 + || (mode != QPainter::CompositionMode_SourceOver + && mode != QPainter::CompositionMode_Source)) + { + blend_src_generic(count, spans, userData); return; } - SRC buffer[buffer_size]; + quint16 buffer[buffer_size]; const int image_width = data->texture.width; const int image_height = data->texture.height; @@ -6021,13 +4905,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); int x = int((data->m21 * cy @@ -6037,10 +4922,17 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; - const SRC *end = buffer + l; - SRC *b = buffer; while (b < end) { int px = (x >> 16) % image_width; int py = (y >> 16) % image_height; @@ -6050,25 +4942,15 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp if (py < 0) py += image_height; - *b = ((SRC*)data->texture.scanLine(py))[px]; + *b = ((quint16 *)data->texture.scanLine(py))[px]; ++b; x += fdx; y += fdy; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -6082,13 +4964,14 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp while (count--) { const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; - if (coverage == 0) { + const quint8 alpha = (coverage + 1) >> 3; + const quint8 ialpha = 0x20 - alpha; + if (alpha == 0) { ++spans; continue; } - DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) - + spans->x; + quint16 *dest = (quint16 *)data->rasterBuffer->scanLine(spans->y) + spans->x; const qreal cx = spans->x + qreal(0.5); const qreal cy = spans->y + qreal(0.5); @@ -6099,9 +4982,17 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp int length = spans->len; while (length) { - const int l = qMin(length, buffer_size); - const SRC *end = buffer + l; - SRC *b = buffer; + int l; + quint16 *b; + if (ialpha == 0) { + l = length; + b = dest; + } else { + l = qMin(length, buffer_size); + b = buffer; + } + const quint16 *end = b + l; + while (b < end) { const qreal iw = w == 0 ? 1 : 1 / w; const qreal tx = x * iw; @@ -6117,7 +5008,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp if (py < 0) py += image_height; - *b = ((SRC*)data->texture.scanLine(py))[px]; + *b = ((quint16 *)data->texture.scanLine(py))[px]; ++b; x += fdx; @@ -6127,18 +5018,9 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp if (!w) w += fdw; } - if (!SRC::hasAlpha() && coverage == 255) { - qt_memconvert(dest, buffer, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) - { - blendUntransformed_dest24(dest, buffer, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { - blendUntransformed_dest16(dest, buffer, coverage, l); - } else { - blendUntransformed_unaligned(dest, buffer, coverage, l); - } + + if (ialpha != 0) + blend_sourceOver_rgb16_rgb16(dest, buffer, l, alpha, ialpha); dest += l; length -= l; @@ -6148,185 +5030,122 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp } } -static void blend_transformed_tiled_rgb888(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_argb6666(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_rgb666(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, - void *userData) -{ - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) - blendTransformedTiled<qrgb565, qargb8565>(count, spans, userData); - else if (data->texture.format == QImage::Format_RGB16) - blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData); - else - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_argb8555(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_rgb555(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_argb4444(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -static void blend_transformed_tiled_rgb444(int count, const QSpan *spans, - void *userData) -{ - blend_src_generic<RegularSpans>(count, spans, userData); -} - -# define SPANFUNC_POINTER(Name, Arg) Name<Arg> - /* Image formats here are target formats */ static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats] = { // Untransformed { 0, // Invalid - SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_untransformed_argb, RegularSpans), // ARGB32_Premultiplied + blend_untransformed_generic, // Mono + blend_untransformed_generic, // MonoLsb + blend_untransformed_generic, // Indexed8 + blend_untransformed_generic, // RGB32 + blend_untransformed_generic, // ARGB32 + blend_untransformed_argb, // ARGB32_Premultiplied blend_untransformed_rgb565, - blend_untransformed_argb8565, - blend_untransformed_rgb666, - blend_untransformed_argb6666, - blend_untransformed_rgb555, - blend_untransformed_argb8555, - blend_untransformed_rgb888, - blend_untransformed_rgb444, - blend_untransformed_argb4444, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, + blend_untransformed_generic, }, // Tiled { 0, // Invalid - SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_tiled_argb, RegularSpans), // ARGB32_Premultiplied + blend_tiled_generic, // Mono + blend_tiled_generic, // MonoLsb + blend_tiled_generic, // Indexed8 + blend_tiled_generic, // RGB32 + blend_tiled_generic, // ARGB32 + blend_tiled_argb, // ARGB32_Premultiplied blend_tiled_rgb565, - blend_tiled_argb8565, - blend_tiled_rgb666, - blend_tiled_argb6666, - blend_tiled_rgb555, - blend_tiled_argb8555, - blend_tiled_rgb888, - blend_tiled_rgb444, - blend_tiled_argb4444, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, + blend_tiled_generic, }, // Transformed { 0, // Invalid - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_transformed_argb, RegularSpans), // ARGB32_Premultiplied + blend_src_generic, // Mono + blend_src_generic, // MonoLsb + blend_src_generic, // Indexed8 + blend_src_generic, // RGB32 + blend_src_generic, // ARGB32 + blend_transformed_argb, // ARGB32_Premultiplied blend_transformed_rgb565, - blend_transformed_argb8565, - blend_transformed_rgb666, - blend_transformed_argb6666, - blend_transformed_rgb555, - blend_transformed_argb8555, - blend_transformed_rgb888, - blend_transformed_rgb444, - blend_transformed_argb4444, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, }, // TransformedTiled { 0, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_transformed_tiled_argb, RegularSpans), // ARGB32_Premultiplied + blend_src_generic, // Mono + blend_src_generic, // MonoLsb + blend_src_generic, // Indexed8 + blend_src_generic, // RGB32 + blend_src_generic, // ARGB32 + blend_transformed_tiled_argb, // ARGB32_Premultiplied blend_transformed_tiled_rgb565, - blend_transformed_tiled_argb8565, - blend_transformed_tiled_rgb666, - blend_transformed_tiled_argb6666, - blend_transformed_tiled_rgb555, - blend_transformed_tiled_argb8555, - blend_transformed_tiled_rgb888, - blend_transformed_tiled_rgb444, - blend_transformed_tiled_argb4444 + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic }, // Bilinear { 0, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied + blend_src_generic, // Mono + blend_src_generic, // MonoLsb + blend_src_generic, // Indexed8 + blend_src_generic, // RGB32 + blend_src_generic, // ARGB32 + blend_src_generic, // ARGB32_Premultiplied blend_transformed_bilinear_rgb565, - blend_transformed_bilinear_argb8565, - blend_transformed_bilinear_rgb666, - blend_transformed_bilinear_argb6666, - blend_transformed_bilinear_rgb555, - blend_transformed_bilinear_argb8555, - blend_transformed_bilinear_rgb888, - blend_transformed_bilinear_rgb444, - blend_transformed_bilinear_argb4444, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, + blend_src_generic, }, // BilinearTiled { 0, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB6666_Premultiplied - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB555 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8555_Premultiplied - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB888 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB444 - SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB4444_Premultiplied + blend_src_generic, // Mono + blend_src_generic, // MonoLsb + blend_src_generic, // Indexed8 + blend_src_generic, // RGB32 + blend_src_generic, // ARGB32 + blend_src_generic, // ARGB32_Premultiplied + blend_src_generic, // RGB16 + blend_src_generic, // ARGB8565_Premultiplied + blend_src_generic, // RGB666 + blend_src_generic, // ARGB6666_Premultiplied + blend_src_generic, // RGB555 + blend_src_generic, // ARGB8555_Premultiplied + blend_src_generic, // RGB888 + blend_src_generic, // RGB444 + blend_src_generic, // ARGB4444_Premultiplied } }; @@ -6339,14 +5158,11 @@ void qBlendTexture(int count, const QSpan *spans, void *userData) template <class DST> inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, - int x, int y, quint32 color, + int x, int y, DST color, const uchar *map, - int mapWidth, int mapHeight, int mapStride, - DST dummy = 0) + int mapWidth, int mapHeight, int mapStride) { - Q_UNUSED(dummy); - const DST c = qt_colorConvert<DST, quint32>(color, 0); - DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; + DST *dest = reinterpret_cast<DST *>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(DST); if (mapWidth > 8) { @@ -6360,7 +5176,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, ++n; } else { if (n) { - qt_memfill(dest + x0, c, n); + qt_memfill(dest + x0, color, n); x0 += n + 1; n = 0; } else { @@ -6375,7 +5191,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, } } if (n) - qt_memfill(dest + x0, c, n); + qt_memfill(dest + x0, color, n); dest += destStride; map += mapStride; } @@ -6387,7 +5203,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, if (s & 0x80) { ++n; } else if (n) { - qt_memfill(dest + x0, c, n); + qt_memfill(dest + x0, color, n); x0 += n + 1; n = 0; } else { @@ -6395,7 +5211,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, } } if (n) - qt_memfill(dest + x0, c, n); + qt_memfill(dest + x0, color, n); dest += destStride; map += mapStride; } @@ -6448,7 +5264,7 @@ static void qt_gradient_quint32(int count, const QSpan *spans, void *userData) } } else { - blend_src_generic<RegularSpans>(count, spans, userData); + blend_src_generic(count, spans, userData); } } @@ -6496,7 +5312,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) data->solid.color = oldColor; } else { - blend_src_generic<RegularSpans>(count, spans, userData); + blend_src_generic(count, spans, userData); } } @@ -6514,7 +5330,7 @@ inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, const uchar *map, int mapWidth, int mapHeight, int mapStride) { - qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color, + qt_bitmapblit_template<quint16>(rasterBuffer, x, y, qConvertRgb32To16(color), map, mapWidth, mapHeight, mapStride); } @@ -6572,7 +5388,7 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, int mapWidth, int mapHeight, int mapStride, const QClipData *) { - const quint16 c = qt_colorConvert<quint16, quint32>(color, 0); + const quint16 c = qConvertRgb32To16(color); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); @@ -6838,41 +5654,25 @@ static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, } } -template <class T> -inline void qt_rectfill_template(QRasterBuffer *rasterBuffer, - int x, int y, int width, int height, - quint32 color, T dummy = 0) +static void qt_rectfill_quint32(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + quint32 color) { - Q_UNUSED(dummy); - - qt_rectfill<T>(reinterpret_cast<T*>(rasterBuffer->buffer()), - qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0), - x, y, width, height, rasterBuffer->bytesPerLine()); + qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), + color, x, y, width, height, rasterBuffer->bytesPerLine()); } -#define QT_RECTFILL(T) \ - inline static void qt_rectfill_##T(QRasterBuffer *rasterBuffer, \ - int x, int y, int width, int height, \ - quint32 color) \ - { \ - qt_rectfill_template<T>(rasterBuffer, x, y, width, height, color); \ - } - -QT_RECTFILL(quint32) -QT_RECTFILL(quint16) -QT_RECTFILL(qargb8565) -QT_RECTFILL(qrgb666) -QT_RECTFILL(qargb6666) -QT_RECTFILL(qrgb555) -QT_RECTFILL(qargb8555) -QT_RECTFILL(qrgb888) -QT_RECTFILL(qrgb444) -QT_RECTFILL(qargb4444) -#undef QT_RECTFILL +static void qt_rectfill_quint16(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + quint32 color) +{ + qt_rectfill<quint16>(reinterpret_cast<quint16 *>(rasterBuffer->buffer()), + qConvertRgb32To16(color), x, y, width, height, rasterBuffer->bytesPerLine()); +} -inline static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, - int x, int y, int width, int height, - quint32 color) +static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, + int x, int y, int width, int height, + quint32 color) { qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); @@ -6889,19 +5689,19 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = // Format_Mono, { blend_color_generic, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), + blend_src_generic, 0, 0, 0, 0 }, // Format_MonoLSB, { blend_color_generic, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), + blend_src_generic, 0, 0, 0, 0 }, // Format_Indexed8, { blend_color_generic, - SPANFUNC_POINTER(blend_src_generic, RegularSpans), + blend_src_generic, 0, 0, 0, 0 }, // Format_RGB32, @@ -6942,88 +5742,78 @@ DrawHelper qDrawHelper[QImage::NImageFormats] = }, // Format_ARGB8565_Premultiplied { - SPANFUNC_POINTER_BLENDCOLOR(qargb8565), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qargb8565 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_RGB666 { - SPANFUNC_POINTER_BLENDCOLOR(qrgb666), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qrgb666 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_ARGB6666_Premultiplied { - SPANFUNC_POINTER_BLENDCOLOR(qargb6666), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qargb6666 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_RGB555 { - SPANFUNC_POINTER_BLENDCOLOR(qrgb555), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qrgb555 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_ARGB8555_Premultiplied { - SPANFUNC_POINTER_BLENDCOLOR(qargb8555), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qargb8555 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_RGB888 { - SPANFUNC_POINTER_BLENDCOLOR(qrgb888), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qrgb888 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_RGB444 { - SPANFUNC_POINTER_BLENDCOLOR(qrgb444), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qrgb444 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 }, // Format_ARGB4444_Premultiplied { - SPANFUNC_POINTER_BLENDCOLOR(qargb4444), - SPANFUNC_POINTER(blend_src_generic, RegularSpans), - 0, 0, 0, - qt_rectfill_qargb4444 + blend_color_generic, + blend_src_generic, + 0, 0, 0, 0 } }; #if defined(Q_CC_MSVC) && !defined(_MIPS_) -template <class DST, class SRC> -inline void qt_memfill_template(DST *dest, SRC color, int count) +template <class T> +inline void qt_memfill_template(T *dest, T color, int count) { - const DST c = qt_colorConvert<DST, SRC>(color, 0); while (count--) - *dest++ = c; + *dest++ = color; } #else -template <class DST, class SRC> -inline void qt_memfill_template(DST *dest, SRC color, int count) +template <class T> +inline void qt_memfill_template(T *dest, T color, int count) { - const DST c = qt_colorConvert<DST, SRC>(color, 0); int n = (count + 7) / 8; switch (count & 0x07) { - case 0: do { *dest++ = c; - case 7: *dest++ = c; - case 6: *dest++ = c; - case 5: *dest++ = c; - case 4: *dest++ = c; - case 3: *dest++ = c; - case 2: *dest++ = c; - case 1: *dest++ = c; + case 0: do { *dest++ = color; + case 7: *dest++ = color; + case 6: *dest++ = color; + case 5: *dest++ = color; + case 4: *dest++ = color; + case 3: *dest++ = color; + case 2: *dest++ = color; + case 1: *dest++ = color; } while (--n > 0); } } @@ -7053,7 +5843,7 @@ inline void qt_memfill_template(quint16 *dest, quint16 value, int count) static void qt_memfill_quint16(quint16 *dest, quint16 color, int count) { - qt_memfill_template<quint16, quint16>(dest, color, count); + qt_memfill_template<quint16>(dest, color, count); } typedef void (*qt_memfill32_func)(quint32 *dest, quint32 value, int count); @@ -7067,8 +5857,8 @@ qt_memfill16_func qt_memfill16 = qt_memfill16_setup; void qInitDrawhelperAsm() { - qt_memfill32 = qt_memfill_template<quint32, quint32>; - qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>; + qt_memfill32 = qt_memfill_template<quint32>; + qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16>; CompositionFunction *functionForModeAsm = 0; CompositionFunctionSolid *functionForModeSolidAsm = 0; diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index c3dd4fb1ef..895b44dc17 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -198,7 +198,7 @@ void qt_blend_rgb16_on_argb32_neon(uchar *destPixels, int dbpl, while (h--) { for (int x=0; x<w; ++x) - dst[x] = INTERPOLATE_PIXEL_255(qt_colorConvert(src[x], dst[x]), a, dst[x], ia); + dst[x] = INTERPOLATE_PIXEL_255(qConvertRgb16To32(src[x]), a, dst[x], ia); dst += dbpl; src += sbpl; } diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index bf8eadcc03..2e88fe718a 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -657,1059 +657,22 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) { | (((255*qGreen(p)) / qAlpha(p)) << 8) \ | ((255*qBlue(p)) / qAlpha(p)))) -template <class DST, class SRC> -inline DST qt_colorConvert(SRC color, DST dummy) -{ - Q_UNUSED(dummy); - return DST(color); -} - - -template <> -inline quint32 qt_colorConvert(quint16 color, quint32 dummy) -{ - Q_UNUSED(dummy); - const int r = (color & 0xf800); - const int g = (color & 0x07e0); - const int b = (color & 0x001f); - const int tr = (r >> 8) | (r >> 13); - const int tg = (g >> 3) | (g >> 9); - const int tb = (b << 3) | (b >> 2); - - return qRgb(tr, tg, tb); -} - -template <> -inline quint16 qt_colorConvert(quint32 color, quint16 dummy) -{ - Q_UNUSED(dummy); - const int r = qRed(color) << 8; - const int g = qGreen(color) << 3; - const int b = qBlue(color) >> 3; - - return (r & 0xf800) | (g & 0x07e0)| (b & 0x001f); -} - -class quint32p -{ -public: - inline quint32p(quint32 v) : data(PREMUL(v)) {} - - inline operator quint32() const { return data; } - - inline operator quint16() const - { - return qt_colorConvert<quint16, quint32>(data, 0); - } - - Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v) - { - quint32p p; - p.data = v; - return p; - } - -private: - quint32p() {} - quint32 data; -} Q_PACKED; - -class qabgr8888 -{ -public: - inline qabgr8888(quint32 v) - { - data = qRgba(qBlue(v), qGreen(v), qRed(v), qAlpha(v)); - } - - inline bool operator==(const qabgr8888 &v) const { return data == v.data; } - -private: - quint32 data; -} Q_PACKED; - -class qrgb565; - -class qargb8565 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } - - inline qargb8565() {} - inline qargb8565(quint32 v); - inline explicit qargb8565(quint32p v); - inline qargb8565(const qargb8565 &v); - inline qargb8565(const qrgb565 &v); - - inline operator quint32() const; - inline operator quint16() const; - - inline quint8 alpha() const { return data[0]; } - inline qargb8565 truncedAlpha() { - data[0] &= 0xf8; - data[1] &= 0xdf; - return *this; - } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } - - inline qargb8565 byte_mul(quint8 a) const; - inline qargb8565 operator+(qargb8565 v) const; - inline bool operator==(const qargb8565 &v) const; - - inline quint32 rawValue() const; - inline quint16 rawValue16() const; - -private: - friend class qrgb565; - - quint8 data[3]; -} Q_PACKED; - -class qrgb565 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } - - qrgb565(int v = 0) : data(v) {} - - inline explicit qrgb565(quint32p v); - inline explicit qrgb565(quint32 v); - inline explicit qrgb565(const qargb8565 &v); - - inline operator quint32() const; - inline operator quint16() const; - - inline qrgb565 operator+(qrgb565 v) const; - - inline quint8 alpha() const { return 0xff; } - inline qrgb565 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } - - inline qrgb565 byte_mul(quint8 a) const; - - inline bool operator==(const qrgb565 &v) const; - inline quint16 rawValue() const { return data; } - -private: - friend class qargb8565; - - quint16 data; -} Q_PACKED; - -qargb8565::qargb8565(quint32 v) -{ - *this = qargb8565(quint32p(v)); -} - -qargb8565::qargb8565(quint32p v) -{ - data[0] = qAlpha(v); - const int r = qRed(v); - const int g = qGreen(v); - const int b = qBlue(v); - data[1] = ((g << 3) & 0xe0) | (b >> 3); - data[2] = (r & 0xf8) | (g >> 5); -} - -qargb8565::qargb8565(const qargb8565 &v) -{ - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = v.data[2]; -} - -qargb8565::qargb8565(const qrgb565 &v) -{ - data[0] = 0xff; - data[1] = v.data & 0xff; - data[2] = v.data >> 8; -} - -qargb8565::operator quint32() const -{ - const quint16 rgb = (data[2] << 8) | data[1]; - const int a = data[0]; - const int r = (rgb & 0xf800); - const int g = (rgb & 0x07e0); - const int b = (rgb & 0x001f); - const int tr = qMin(a, (r >> 8) | (r >> 13)); - const int tg = qMin(a, (g >> 3) | (g >> 9)); - const int tb = qMin(a, (b << 3) | (b >> 2)); - return qRgba(tr, tg, tb, data[0]); -} - -qargb8565::operator quint16() const -{ - return (data[2] << 8) | data[1]; -} - -qargb8565 qargb8565::operator+(qargb8565 v) const -{ - qargb8565 t; - t.data[0] = data[0] + v.data[0]; - const quint16 rgb = ((data[2] + v.data[2]) << 8) - + (data[1] + v.data[1]); - t.data[1] = rgb & 0xff; - t.data[2] = rgb >> 8; - return t; -} - -qargb8565 qargb8565::byte_mul(quint8 a) const -{ - qargb8565 result; - result.data[0] = (data[0] * a) >> 5; - - const quint16 x = (data[2] << 8) | data[1]; - const quint16 t = ((((x & 0x07e0) >> 5) * a) & 0x07e0) | - ((((x & 0xf81f) * a) >> 5) & 0xf81f); - result.data[1] = t & 0xff; - result.data[2] = t >> 8; - return result; -} - -bool qargb8565::operator==(const qargb8565 &v) const -{ - return data[0] == v.data[0] - && data[1] == v.data[1] - && data[2] == v.data[2]; -} - -quint32 qargb8565::rawValue() const -{ - return (data[2] << 16) | (data[1] << 8) | data[0]; -} - -quint16 qargb8565::rawValue16() const -{ - return (data[2] << 8) | data[1]; -} - -qrgb565::qrgb565(quint32p v) -{ - *this = qrgb565(quint32(v)); -} - -qrgb565::qrgb565(quint32 v) -{ - const int r = qRed(v) << 8; - const int g = qGreen(v) << 3; - const int b = qBlue(v) >> 3; - - data = (r & 0xf800) | (g & 0x07e0)| (b & 0x001f); -} - -qrgb565::qrgb565(const qargb8565 &v) -{ - data = (v.data[2] << 8) | v.data[1]; -} - -qrgb565::operator quint32() const -{ - const int r = (data & 0xf800); - const int g = (data & 0x07e0); - const int b = (data & 0x001f); - const int tr = (r >> 8) | (r >> 13); - const int tg = (g >> 3) | (g >> 9); - const int tb = (b << 3) | (b >> 2); - return qRgb(tr, tg, tb); -} - -qrgb565::operator quint16() const -{ - return data; -} - -qrgb565 qrgb565::operator+(qrgb565 v) const -{ - qrgb565 t; - t.data = data + v.data; - return t; -} - -qrgb565 qrgb565::byte_mul(quint8 a) const -{ - qrgb565 result; - result.data = ((((data & 0x07e0) >> 5) * a) & 0x07e0) | - ((((data & 0xf81f) * a) >> 5) & 0xf81f); - return result; -} - -bool qrgb565::operator==(const qrgb565 &v) const -{ - return data == v.data; -} - -class qbgr565 -{ -public: - inline qbgr565(quint16 v) - { - data = ((v & 0x001f) << 11) | - (v & 0x07e0) | - ((v & 0xf800) >> 11); - } - - inline bool operator==(const qbgr565 &v) const - { - return data == v.data; - } - -private: - quint16 data; -} Q_PACKED; - -class qrgb555; - -class qargb8555 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } - - qargb8555() {} - inline qargb8555(quint32 v); - inline explicit qargb8555(quint32p v); - inline qargb8555(const qargb8555 &v); - inline qargb8555(const qrgb555 &v); - - inline operator quint32() const; - - inline quint8 alpha() const { return data[0]; } - inline qargb8555 truncedAlpha() { data[0] &= 0xf8; return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } - - inline qargb8555 operator+(qargb8555 v) const; - inline qargb8555 byte_mul(quint8 a) const; - - inline bool operator==(const qargb8555 &v) const; - - inline quint32 rawValue() const; - -private: - friend class qrgb555; - quint8 data[3]; -} Q_PACKED; - -class qrgb555 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } - - inline qrgb555(int v = 0) : data(v) {} - - inline explicit qrgb555(quint32p v) { *this = qrgb555(quint32(v)); } - - inline explicit qrgb555(quint32 v) - { - const int r = qRed(v) << 7; - const int g = qGreen(v) << 2; - const int b = qBlue(v) >> 3; - - data = (r & 0x7c00) | (g & 0x03e0) | (b & 0x001f); - } - - inline explicit qrgb555(quint16 v) - { - data = ((v >> 1) & (0x7c00 | 0x03e0)) | - (v & 0x001f); - } - - inline explicit qrgb555(const qargb8555 &v); - - inline operator quint32() const - { - const int r = (data & 0x7c00); - const int g = (data & 0x03e0); - const int b = (data & 0x001f); - const int tr = (r >> 7) | (r >> 12); - const int tg = (g >> 2) | (g >> 7); - const int tb = (b << 3) | (b >> 2); - - return qRgb(tr, tg, tb); - } - - inline operator quint16() const - { - const int r = ((data & 0x7c00) << 1) & 0xf800; - const int g = (((data & 0x03e0) << 1) | ((data >> 4) & 0x0020)) & 0x07e0; - const int b = (data & 0x001f); - - return r | g | b; - } - - inline qrgb555 operator+(qrgb555 v) const; - inline qrgb555 byte_mul(quint8 a) const; - - inline quint8 alpha() const { return 0xff; } - inline qrgb555 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); } - - inline bool operator==(const qrgb555 &v) const { return v.data == data; } - inline bool operator!=(const qrgb555 &v) const { return v.data != data; } - - inline quint16 rawValue() const { return data; } - -private: - friend class qargb8555; - friend class qbgr555; - quint16 data; - -} Q_PACKED; - -qrgb555::qrgb555(const qargb8555 &v) -{ - data = (v.data[2] << 8) | v.data[1]; -} - -qrgb555 qrgb555::operator+(qrgb555 v) const -{ - qrgb555 t; - t.data = data + v.data; - return t; -} - -qrgb555 qrgb555::byte_mul(quint8 a) const -{ - quint16 t = (((data & 0x3e0) * a) >> 5) & 0x03e0; - t |= (((data & 0x7c1f) * a) >> 5) & 0x7c1f; - - qrgb555 result; - result.data = t; - return result; -} - -class qbgr555 -{ -public: - inline qbgr555(quint32 v) { *this = qbgr555(qrgb555(v)); } - - inline qbgr555(qrgb555 v) - { - data = ((v.data & 0x001f) << 10) | - (v.data & 0x03e0) | - ((v.data & 0x7c00) >> 10); - } - - inline bool operator==(const qbgr555 &v) const - { - return data == v.data; - } - -private: - quint16 data; -} Q_PACKED; - -qargb8555::qargb8555(quint32 v) -{ - v = quint32p(v); - data[0] = qAlpha(v); - const int r = qRed(v); - const int g = qGreen(v); - const int b = qBlue(v); - data[1] = ((g << 2) & 0xe0) | (b >> 3); - data[2] = ((r >> 1) & 0x7c) | (g >> 6); - -} - -qargb8555::qargb8555(quint32p v) -{ - data[0] = qAlpha(v); - const int r = qRed(v); - const int g = qGreen(v); - const int b = qBlue(v); - data[1] = ((g << 2) & 0xe0) | (b >> 3); - data[2] = ((r >> 1) & 0x7c) | (g >> 6); -} - -qargb8555::qargb8555(const qargb8555 &v) -{ - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = v.data[2]; -} - -qargb8555::qargb8555(const qrgb555 &v) -{ - data[0] = 0xff; - data[1] = v.data & 0xff; - data[2] = v.data >> 8; -} - -qargb8555::operator quint32() const -{ - const quint16 rgb = (data[2] << 8) | data[1]; - const int r = (rgb & 0x7c00); - const int g = (rgb & 0x03e0); - const int b = (rgb & 0x001f); - const int tr = (r >> 7) | (r >> 12); - const int tg = (g >> 2) | (g >> 7); - const int tb = (b << 3) | (b >> 2); - - return qRgba(tr, tg, tb, data[0]); -} - -bool qargb8555::operator==(const qargb8555 &v) const -{ - return data[0] == v.data[0] - && data[1] == v.data[1] - && data[2] == v.data[2]; -} - -quint32 qargb8555::rawValue() const -{ - return (data[2] << 16) | (data[1] << 8) | data[0]; -} - -qargb8555 qargb8555::operator+(qargb8555 v) const -{ - qargb8555 t; - t.data[0] = data[0] + v.data[0]; - const quint16 rgb = ((data[2] + v.data[2]) << 8) - + (data[1] + v.data[1]); - t.data[1] = rgb & 0xff; - t.data[2] = rgb >> 8; - return t; -} - -qargb8555 qargb8555::byte_mul(quint8 a) const -{ - qargb8555 result; - result.data[0] = (data[0] * a) >> 5; - - const quint16 x = (data[2] << 8) | data[1]; - quint16 t = (((x & 0x3e0) * a) >> 5) & 0x03e0; - t |= (((x & 0x7c1f) * a) >> 5) & 0x7c1f; - result.data[1] = t & 0xff; - result.data[2] = t >> 8; - return result; - -} - -class qrgb666; - -class qargb6666 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } - - inline qargb6666() {} - inline qargb6666(quint32 v) { *this = qargb6666(quint32p(v)); } - inline explicit qargb6666(quint32p v); - inline qargb6666(const qargb6666 &v); - inline qargb6666(const qrgb666 &v); - - inline operator quint32 () const; - - inline quint8 alpha() const; - inline qargb6666 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } - - inline qargb6666 byte_mul(quint8 a) const; - inline qargb6666 operator+(qargb6666 v) const; - inline bool operator==(const qargb6666 &v) const; - - inline quint32 rawValue() const; - -private: - friend class qrgb666; - quint8 data[3]; - -} Q_PACKED; - -class qrgb666 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } - - inline qrgb666() {} - inline qrgb666(quint32 v); - inline qrgb666(const qargb6666 &v); - - inline operator quint32 () const; - - inline quint8 alpha() const { return 0xff; } - inline qrgb666 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; } - - inline qrgb666 operator+(qrgb666 v) const; - inline qrgb666 byte_mul(quint8 a) const; - - inline bool operator==(const qrgb666 &v) const; - inline bool operator!=(const qrgb666 &v) const { return !(*this == v); } - - inline quint32 rawValue() const - { - return (data[2] << 16) | (data[1] << 8) | data[0]; - } - -private: - friend class qargb6666; - - quint8 data[3]; -} Q_PACKED; - -qrgb666::qrgb666(quint32 v) -{ - const uchar b = qBlue(v); - const uchar g = qGreen(v); - const uchar r = qRed(v); - const uint p = (b >> 2) | ((g >> 2) << 6) | ((r >> 2) << 12); - data[0] = qBlue(p); - data[1] = qGreen(p); - data[2] = qRed(p); -} - -qrgb666::qrgb666(const qargb6666 &v) -{ - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = v.data[2] & 0x03; -} - -qrgb666::operator quint32 () const -{ - const uchar r = (data[2] << 6) | ((data[1] & 0xf0) >> 2) | (data[2] & 0x3); - const uchar g = (data[1] << 4) | ((data[0] & 0xc0) >> 4) | ((data[1] & 0x0f) >> 2); - const uchar b = (data[0] << 2) | ((data[0] & 0x3f) >> 4); - return qRgb(r, g, b); -} - -qrgb666 qrgb666::operator+(qrgb666 v) const -{ - const quint32 x1 = (data[2] << 16) | (data[1] << 8) | data[0]; - const quint32 x2 = (v.data[2] << 16) | (v.data[1] << 8) | v.data[0]; - const quint32 t = x1 + x2; - qrgb666 r; - r.data[0] = t & 0xff; - r.data[1] = (t >> 8) & 0xff; - r.data[2] = (t >> 16) & 0xff; - return r; -} - -qrgb666 qrgb666::byte_mul(quint8 a) const -{ - const quint32 x = (data[2] << 16) | (data[1] << 8) | data[0]; - const quint32 t = ((((x & 0x03f03f) * a) >> 6) & 0x03f03f) | - ((((x & 0x000fc0) * a) >> 6) & 0x000fc0); - - qrgb666 r; - r.data[0] = t & 0xff; - r.data[1] = (t >> 8) & 0xff; - r.data[2] = (t >> 16) & 0xff; - return r; -} - -bool qrgb666::operator==(const qrgb666 &v) const -{ - return (data[0] == v.data[0] && - data[1] == v.data[1] && - data[2] == v.data[2]); -} - -qargb6666::qargb6666(quint32p v) -{ - const quint8 b = qBlue(v) >> 2; - const quint8 g = qGreen(v) >> 2; - const quint8 r = qRed(v) >> 2; - const quint8 a = qAlpha(v) >> 2; - const uint p = (a << 18) | (r << 12) | (g << 6) | b; - data[0] = qBlue(p); - data[1] = qGreen(p); - data[2] = qRed(p); -} - -qargb6666::qargb6666(const qargb6666 &v) -{ - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = v.data[2]; -} - -qargb6666::qargb6666(const qrgb666 &v) -{ - data[0] = v.data[0]; - data[1] = v.data[1]; - data[2] = (v.data[2] | 0xfc); -} - -qargb6666::operator quint32 () const -{ - const quint8 r = (data[2] << 6) | ((data[1] & 0xf0) >> 2) | (data[2] & 0x3); - const quint8 g = (data[1] << 4) | ((data[0] & 0xc0) >> 4) | ((data[1] & 0x0f) >> 2); - const quint8 b = (data[0] << 2) | ((data[0] & 0x3f) >> 4); - const quint8 a = (data[2] & 0xfc) | (data[2] >> 6); - return qRgba(r, g, b, a); -} - -qargb6666 qargb6666::operator+(qargb6666 v) const -{ - const quint32 x1 = (data[2] << 16) | (data[1] << 8) | data[0]; - const quint32 x2 = (v.data[2] << 16) | (v.data[1] << 8) | v.data[0]; - const quint32 t = x1 + x2; - qargb6666 r; - r.data[0] = t & 0xff; - r.data[1] = (t >> 8) & 0xff; - r.data[2] = (t >> 16) & 0xff; - return r; -} - -quint8 qargb6666::alpha() const -{ - return (data[2] & 0xfc) | (data[2] >> 6); -} - -inline qargb6666 qargb6666::byte_mul(quint8 a) const -{ - const quint32 x = (data[2] << 16) | (data[1] << 8) | data[0]; - const quint32 t = ((((x & 0x03f03f) * a) >> 6) & 0x03f03f) | - ((((x & 0xfc0fc0) * a) >> 6) & 0xfc0fc0); - - qargb6666 r; - r.data[0] = t & 0xff; - r.data[1] = (t >> 8) & 0xff; - r.data[2] = (t >> 16) & 0xff; - return r; -} - -bool qargb6666::operator==(const qargb6666 &v) const -{ - return data[0] == v.data[0] - && data[1] == v.data[1] - && data[2] == v.data[2]; -} - -quint32 qargb6666::rawValue() const -{ - return (data[2] << 16) | (data[1] << 8) | data[0]; -} - -class qrgb888 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } - - inline qrgb888() {} - inline qrgb888(quint32 v); - - inline operator quint32() const; - - inline quint8 alpha() const { return 0xff; } - inline qrgb888 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return a; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 255 - a; } - - inline qrgb888 byte_mul(quint8 a) const; - inline qrgb888 operator+(qrgb888 v) const; - inline bool operator==(qrgb888 v) const; - - inline quint32 rawValue() const; - -private: +struct quint24 { + quint24(uint value); + operator uint() const; uchar data[3]; - } Q_PACKED; -qrgb888::qrgb888(quint32 v) +inline quint24::quint24(uint value) { - data[0] = qRed(v); - data[1] = qGreen(v); - data[2] = qBlue(v); + data[0] = uchar(value); + data[1] = uchar(value >> 8); + data[2] = uchar(value >> 16); } -qrgb888::operator quint32() const +inline quint24::operator uint() const { - return qRgb(data[0], data[1], data[2]); -} - -qrgb888 qrgb888::operator+(qrgb888 v) const -{ - qrgb888 t = *this; - t.data[0] += v.data[0]; - t.data[1] += v.data[1]; - t.data[2] += v.data[2]; - return t; -} - -qrgb888 qrgb888::byte_mul(quint8 a) const -{ - quint32 x(*this); - - quint32 t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t &= 0xff00ff; - - x = ((x >> 8) & 0xff00ff) * a; - x = (x + ((x >> 8) & 0xff00ff) + 0x800080); - x &= 0xff00ff00; - x |= t; - return qrgb888(x); -} - -bool qrgb888::operator==(qrgb888 v) const -{ - return (data[0] == v.data[0] && - data[1] == v.data[1] && - data[2] == v.data[2]); -} - -quint32 qrgb888::rawValue() const -{ - return (data[2] << 16) | (data[1] << 8) | data[0]; -} - -template <> -inline qrgb888 qt_colorConvert(quint32 color, qrgb888 dummy) -{ - Q_UNUSED(dummy); - return qrgb888(color); -} - -template <> -inline quint32 qt_colorConvert(qrgb888 color, quint32 dummy) -{ - Q_UNUSED(dummy); - return quint32(color); -} - -// hw: endianess?? -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]; - } - -private: - uchar data[3]; -} Q_PACKED; - -template <> -inline quint24 qt_colorConvert(quint32 color, quint24 dummy) -{ - Q_UNUSED(dummy); - return quint24(color); -} - -// hw: endianess?? -class quint18 -{ -public: - inline quint18(quint32 v) - { - uchar b = qBlue(v); - uchar g = qGreen(v); - uchar r = qRed(v); - uint p = (b >> 2) | ((g >> 2) << 6) | ((r >> 2) << 12); - data[0] = qBlue(p); - data[1] = qGreen(p); - data[2] = qRed(p); - } - - inline operator quint32 () - { - const uchar r = (data[2] << 6) | ((data[1] & 0xf0) >> 2) | (data[2] & 0x3); - const uchar g = (data[1] << 4) | ((data[0] & 0xc0) >> 4) | ((data[1] & 0x0f) >> 2); - const uchar b = (data[0] << 2) | ((data[0] & 0x3f) >> 4); - return qRgb(r, g, b); - } - -private: - uchar data[3]; -} Q_PACKED; - -template <> -inline quint18 qt_colorConvert(quint32 color, quint18 dummy) -{ - Q_UNUSED(dummy); - return quint18(color); -} - -class qrgb444; - -class qargb4444 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; } - - inline qargb4444() {} - inline qargb4444(quint32 v) { *this = qargb4444(quint32p(v)); } - inline explicit qargb4444(quint32p v); - inline qargb4444(const qrgb444 &v); - - inline operator quint32() const; - inline operator quint8() const; - - inline qargb4444 operator+(qargb4444 v) const; - - inline quint8 alpha() const { return ((data & 0xf000) >> 8) | ((data & 0xf000) >> 12); } - inline qargb4444 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } - inline qargb4444 byte_mul(quint8 a) const; - - inline bool operator==(const qargb4444 &v) const { return data == v.data; } - - inline quint16 rawValue() const { return data; } - -private: - friend class qrgb444; - quint16 data; - -} Q_PACKED; - -class qrgb444 -{ -public: - Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; } - - inline qrgb444() {} - inline qrgb444(quint32 v); - inline explicit qrgb444(qargb4444 v); - - inline operator quint32() const; - inline operator quint8() const; - - inline qrgb444 operator+(qrgb444 v) const; - inline quint8 alpha() const { return 0xff; } - inline qrgb444 truncedAlpha() { return *this; } - Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; } - Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); } - inline qrgb444 byte_mul(quint8 a) const; - - inline bool operator==(const qrgb444 &v) const { return data == v.data; } - inline bool operator!=(const qrgb444 &v) const { return data != v.data; } - - inline quint16 rawValue() const { return data; } - -private: - friend class qargb4444; - quint16 data; - -} Q_PACKED; - - -qargb4444::qargb4444(quint32p color) -{ - quint32 v = color; - v &= 0xf0f0f0f0; - const int a = qAlpha(v) << 8; - const int r = qRed(v) << 4; - const int g = qGreen(v); - const int b = qBlue(v) >> 4; - - data = a | r | g | b; -} - -qargb4444::qargb4444(const qrgb444 &v) -{ - data = v.data | 0xf000; -} - -qargb4444::operator quint32() const -{ - const int a = (data & 0xf000); - const int r = (data & 0x0f00); - const int g = (data & 0x00f0); - const int b = (data & 0x000f); - const int ta = (a >> 8) | (a >> 12); - const int tr = (r >> 4) | (r >> 8); - const int tg = g | (g >> 4); - const int tb = (b << 4) | b; - - return qRgba(tr, tg, tb, ta); -} - -qargb4444::operator quint8() const -{ - // hw: optimize! - return qt_colorConvert<quint8, quint32>(operator quint32(), 0); -} - -qargb4444 qargb4444::operator+(qargb4444 v) const -{ - qargb4444 t; - t.data = data + v.data; - return t; -} - -qargb4444 qargb4444::byte_mul(quint8 a) const -{ - quint16 t = (((data & 0xf0f0) * a) >> 4) & 0xf0f0; - t |= (((data & 0x0f0f) * a) >> 4) & 0x0f0f; - - qargb4444 result; - result.data = t; - return result; -} - -qrgb444::qrgb444(quint32 v) -{ - v &= 0xf0f0f0f0; - const int r = qRed(v) << 4; - const int g = qGreen(v); - const int b = qBlue(v) >> 4; - - data = r | g | b; -} - -qrgb444::qrgb444(qargb4444 v) -{ - data = v.data & 0x0fff; -} - -qrgb444::operator quint32() const -{ - const int r = (data & 0x0f00); - const int g = (data & 0x00f0); - const int b = (data & 0x000f); - const int tr = (r >> 4) | (r >> 8); - const int tg = g | (g >> 4); - const int tb = (b << 4) | b; - - return qRgb(tr, tg, tb); -} - -qrgb444::operator quint8() const -{ - // hw: optimize! - return qt_colorConvert<quint8, quint32>(operator quint32(), 0); -} - -qrgb444 qrgb444::operator+(qrgb444 v) const -{ - qrgb444 t; - t.data = data + v.data; - return t; -} - -qrgb444 qrgb444::byte_mul(quint8 a) const -{ - quint16 t = (((data & 0xf0f0) * a) >> 4) & 0xf0f0; - t |= (((data & 0x0f0f) * a) >> 4) & 0x0f0f; - - qrgb444 result; - result.data = t; - return result; + return data[0] | (data[1] << 8) | (data[2] << 16); } template <class T> @@ -1769,156 +732,6 @@ inline void qt_rectfill(T *dest, T value, } } -template <class DST, class SRC> -inline void qt_memconvert(DST *dest, const SRC *src, int count) -{ - if (sizeof(DST) == 1) { - while (count) { - int n = 1; - const SRC color = *src++; - const DST dstColor = qt_colorConvert<DST, SRC>(color, 0); - while (--count && (*src == color || dstColor == qt_colorConvert<DST, SRC>(*src, 0))) { - ++n; - ++src; - } - qt_memfill(dest, dstColor, n); - dest += n; - } - } else { - /* Duff's device */ - int n = (count + 7) / 8; - switch (count & 0x07) - { - case 0: do { *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 7: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 6: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 5: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 4: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 3: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 2: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - case 1: *dest++ = qt_colorConvert<DST, SRC>(*src++, 0); - } while (--n > 0); - } - } -} - -#define QT_TRIVIAL_MEMCONVERT_IMPL(T) \ - template <> \ - inline void qt_memconvert(T *dest, const T *src, int count) \ - { \ - memcpy(dest, src, count * sizeof(T)); \ - } -QT_TRIVIAL_MEMCONVERT_IMPL(quint32) -QT_TRIVIAL_MEMCONVERT_IMPL(qrgb888) -QT_TRIVIAL_MEMCONVERT_IMPL(qargb6666) -QT_TRIVIAL_MEMCONVERT_IMPL(qrgb666) -QT_TRIVIAL_MEMCONVERT_IMPL(quint16) -QT_TRIVIAL_MEMCONVERT_IMPL(qrgb565) -QT_TRIVIAL_MEMCONVERT_IMPL(qargb8565) -QT_TRIVIAL_MEMCONVERT_IMPL(qargb8555) -QT_TRIVIAL_MEMCONVERT_IMPL(qrgb555) -QT_TRIVIAL_MEMCONVERT_IMPL(qargb4444) -QT_TRIVIAL_MEMCONVERT_IMPL(qrgb444) -#undef QT_TRIVIAL_MEMCONVERT_IMPL - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -template <> -inline void qt_memconvert(qrgb666 *dest, const quint32 *src, int count) -{ - if (count < 3) { - switch (count) { - case 2: *dest++ = qrgb666(*src++); - case 1: *dest = qrgb666(*src); - } - return; - } - - const int align = (quintptr(dest) & 3); - switch (align) { - case 1: *dest++ = qrgb666(*src++); --count; - case 2: *dest++ = qrgb666(*src++); --count; - case 3: *dest++ = qrgb666(*src++); --count; - } - - quint32 *dest32 = reinterpret_cast<quint32*>(dest); - int sourceCount = count >> 2; - while (sourceCount--) { - dest32[0] = ((src[1] & 0x00000c00) << 20) - | ((src[1] & 0x000000fc) << 22) - | ((src[0] & 0x00fc0000) >> 6) - | ((src[0] & 0x0000fc00) >> 4) - | ((src[0] & 0x000000fc) >> 2); - dest32[1] = ((src[2] & 0x003c0000) << 10) - | ((src[2] & 0x0000fc00) << 12) - | ((src[2] & 0x000000fc) << 14) - | ((src[1] & 0x00fc0000) >> 14) - | ((src[1] & 0x0000f000) >> 12); - dest32[2] = ((src[3] & 0x00fc0000) << 2) - | ((src[3] & 0x0000fc00) << 4) - | ((src[3] & 0x000000fc) << 6) - | ((src[2] & 0x00c00000) >> 22); - dest32 += 3; - src += 4; - } - - dest = reinterpret_cast<qrgb666*>(dest32); - switch (count & 3) { - case 3: *dest++ = qrgb666(*src++); - case 2: *dest++ = qrgb666(*src++); - case 1: *dest = qrgb666(*src); - } -} -#endif // Q_BYTE_ORDER - -template <class T> -inline void qt_rectcopy(T *dest, const T *src, - int x, int y, int width, int height, - int dstStride, int srcStride) -{ - char *d = (char*)(dest + x) + y * dstStride; - const char *s = (char*)(src); - for (int i = 0; i < height; ++i) { - ::memcpy(d, s, width * sizeof(T)); - d += dstStride; - s += srcStride; - } -} - -template <class DST, class SRC> -inline void qt_rectconvert(DST *dest, const SRC *src, - int x, int y, int width, int height, - int dstStride, int srcStride) -{ - char *d = (char*)(dest + x) + y * dstStride; - const char *s = (char*)(src); - for (int i = 0; i < height; ++i) { - qt_memconvert<DST,SRC>((DST*)d, (const SRC*)s, width); - d += dstStride; - s += srcStride; - } -} - -#define QT_RECTCONVERT_TRIVIAL_IMPL(T) \ - template <> \ - inline void qt_rectconvert(T *dest, const T *src, \ - int x, int y, int width, int height, \ - int dstStride, int srcStride) \ - { \ - qt_rectcopy(dest, src, x, y, width, height, dstStride, srcStride); \ - } -QT_RECTCONVERT_TRIVIAL_IMPL(quint32) -QT_RECTCONVERT_TRIVIAL_IMPL(qrgb888) -QT_RECTCONVERT_TRIVIAL_IMPL(qargb6666) -QT_RECTCONVERT_TRIVIAL_IMPL(qrgb666) -QT_RECTCONVERT_TRIVIAL_IMPL(qrgb565) -QT_RECTCONVERT_TRIVIAL_IMPL(qargb8565) -QT_RECTCONVERT_TRIVIAL_IMPL(quint16) -QT_RECTCONVERT_TRIVIAL_IMPL(qargb8555) -QT_RECTCONVERT_TRIVIAL_IMPL(qrgb555) -QT_RECTCONVERT_TRIVIAL_IMPL(qargb4444) -QT_RECTCONVERT_TRIVIAL_IMPL(qrgb444) -#undef QT_RECTCONVERT_TRIVIAL_IMPL - #define QT_MEMFILL_UINT(dest, length, color) \ qt_memfill<quint32>(dest, color, length); @@ -2137,6 +950,162 @@ void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, uint color, ui void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, int length, uint color, uint const_alpha); void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, int length, uint color, uint const_alpha); + +struct QPixelLayout; +typedef const uint *(QT_FASTCALL *ConvertFunc)(uint *buffer, const uint *src, int count, + const QPixelLayout *layout, const QRgb *clut); + +struct QPixelLayout +{ + // Bits per pixel + enum BPP { + BPPNone, + BPP1MSB, + BPP1LSB, + BPP8, + BPP16, + BPP24, + BPP32, + BPPCount + }; + + // All numbers in bits. + uchar redWidth; + uchar redShift; + uchar greenWidth; + uchar greenShift; + uchar blueWidth; + uchar blueShift; + uchar alphaWidth; + uchar alphaShift; + bool premultiplied; + BPP bpp; + ConvertFunc convertToARGB32PM; + ConvertFunc convertFromARGB32PM; +}; + +template <QPixelLayout::BPP bpp> +uint fetchPixel(const uchar *src, int index); + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1LSB>(const uchar *src, int index) +{ + return (src[index >> 3] >> (index & 7)) & 1; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP1MSB>(const uchar *src, int index) +{ + return (src[index >> 3] >> (~index & 7)) & 1; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP8>(const uchar *src, int index) +{ + return src[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP16>(const uchar *src, int index) +{ + return reinterpret_cast<const quint16 *>(src)[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP24>(const uchar *src, int index) +{ + return reinterpret_cast<const quint24 *>(src)[index]; +} + +template <> +inline uint QT_FASTCALL fetchPixel<QPixelLayout::BPP32>(const uchar *src, int index) +{ + return reinterpret_cast<const uint *>(src)[index]; +} + +template <QPixelLayout::BPP bpp> +inline const uint *QT_FASTCALL fetchPixels(uint *buffer, const uchar *src, int index, int count) +{ + for (int i = 0; i < count; ++i) + buffer[i] = fetchPixel<bpp>(src, index + i); + return buffer; +} + +template <> +inline const uint *QT_FASTCALL fetchPixels<QPixelLayout::BPP32>(uint *, const uchar *src, int index, int) +{ + return reinterpret_cast<const uint *>(src) + index; +} + +typedef const uint *(QT_FASTCALL *FetchPixelsFunc)(uint *buffer, const uchar *src, int index, int count); + + +template <QPixelLayout::BPP width> +void storePixel(uchar *dest, int index, uint pixel); + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP1LSB>(uchar *dest, int index, uint pixel) +{ + if (pixel) + dest[index >> 3] |= 1 << (index & 7); + else + dest[index >> 3] &= ~(1 << (index & 7)); +} + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP1MSB>(uchar *dest, int index, uint pixel) +{ + if (pixel) + dest[index >> 3] |= 1 << (~index & 7); + else + dest[index >> 3] &= ~(1 << (~index & 7)); +} + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP8>(uchar *dest, int index, uint pixel) +{ + dest[index] = uchar(pixel); +} + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP16>(uchar *dest, int index, uint pixel) +{ + reinterpret_cast<quint16 *>(dest)[index] = quint16(pixel); +} + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP24>(uchar *dest, int index, uint pixel) +{ + reinterpret_cast<quint24 *>(dest)[index] = quint24(pixel); +} + +template <> +inline void QT_FASTCALL storePixel<QPixelLayout::BPP32>(uchar *dest, int index, uint pixel) +{ + reinterpret_cast<uint *>(dest)[index] = pixel; +} + +template <QPixelLayout::BPP width> +inline void QT_FASTCALL storePixels(uchar *dest, const uint *src, int index, int count) +{ + for (int i = 0; i < count; ++i) + storePixel<width>(dest, index + i, src[i]); +} + +template <> +inline void QT_FASTCALL storePixels<QPixelLayout::BPP32>(uchar *dest, const uint *src, int index, int count) +{ + memcpy(reinterpret_cast<uint *>(dest) + index, src, count * sizeof(uint)); +} + +typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int index, int count); + +extern QPixelLayout qPixelLayouts[QImage::NImageFormats]; +extern FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount]; +extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount]; + + + QT_END_NAMESPACE #endif // QDRAWHELPER_P_H diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index 17b249a235..300a28158d 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -459,7 +459,7 @@ void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y, quint32 color, const uchar *src, int width, int height, int stride) { - const quint16 c = qt_colorConvert<quint16, quint32>(color, 0); + const quint16 c = qConvertRgb32To16(color); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); diff --git a/src/gui/painting/qdrawhelper_sse_p.h b/src/gui/painting/qdrawhelper_sse_p.h index 81a5001fb3..494ee70fcb 100644 --- a/src/gui/painting/qdrawhelper_sse_p.h +++ b/src/gui/painting/qdrawhelper_sse_p.h @@ -127,7 +127,7 @@ inline void qt_bitmapblit16_sse_template(QRasterBuffer *rasterBuffer, const uchar *src, int width, int height, int stride) { - const quint16 c = qt_colorConvert<quint16, quint32>(color, 0); + const quint16 c = qConvertRgb32To16(color); quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); diff --git a/src/gui/painting/qmemrotate.cpp b/src/gui/painting/qmemrotate.cpp index 5d027b669b..e6fcc3e5dd 100644 --- a/src/gui/painting/qmemrotate.cpp +++ b/src/gui/painting/qmemrotate.cpp @@ -53,36 +53,36 @@ static const int tileSize = 32; #endif #endif -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_cachedRead(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_cachedRead(const T *src, int w, int h, int sstride, T *dest, + int dstride) { const char *s = reinterpret_cast<const char*>(src); char *d = reinterpret_cast<char*>(dest); for (int y = 0; y < h; ++y) { for (int x = w - 1; x >= 0; --x) { - DST *destline = reinterpret_cast<DST*>(d + (w - x - 1) * dstride); - destline[y] = qt_colorConvert<DST,SRC>(src[x], 0); + T *destline = reinterpret_cast<T *>(d + (w - x - 1) * dstride); + destline[y] = src[x]; } s += sstride; - src = reinterpret_cast<const SRC*>(s); + src = reinterpret_cast<const T*>(s); } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedRead(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_cachedRead(const T *src, int w, int h, int sstride, T *dest, + int dstride) { const char *s = reinterpret_cast<const char*>(src); char *d = reinterpret_cast<char*>(dest); s += (h - 1) * sstride; for (int y = h - 1; y >= 0; --y) { - src = reinterpret_cast<const SRC*>(s); + src = reinterpret_cast<const T*>(s); for (int x = 0; x < w; ++x) { - DST *destline = reinterpret_cast<DST*>(d + x * dstride); - destline[h - y - 1] = qt_colorConvert<DST,SRC>(src[x], 0); + T *destline = reinterpret_cast<T *>(d + x * dstride); + destline[h - y - 1] = src[x]; } s -= sstride; } @@ -90,29 +90,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedRead(const SRC *src #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_cachedWrite(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_cachedWrite(const T *src, int w, int h, int sstride, T *dest, + int dstride) { for (int x = w - 1; x >= 0; --x) { - DST *d = dest + (w - x - 1) * dstride; + T *d = dest + (w - x - 1) * dstride; for (int y = 0; y < h; ++y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedWrite(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_cachedWrite(const T *src, int w, int h, int sstride, T *dest, + int dstride) { for (int x = 0; x < w; ++x) { - DST *d = dest + x * dstride; + T *d = dest + x * dstride; for (int y = h - 1; y >= 0; --y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } @@ -123,23 +123,21 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_cachedWrite(const SRC *sr // TODO: packing algorithms should probably be modified on 64-bit architectures -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_packing(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_packing(const T *src, int w, int h, int sstride, T *dest, int dstride) { - sstride /= sizeof(SRC); - dstride /= sizeof(DST); + sstride /= sizeof(T); + dstride /= sizeof(T); - const int pack = sizeof(quint32) / sizeof(DST); - const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(DST); + const int pack = sizeof(quint32) / sizeof(T); + const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T); for (int x = w - 1; x >= 0; --x) { int y = 0; for (int i = 0; i < unaligned; ++i) { - dest[(w - x - 1) * dstride + y] - = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + dest[(w - x - 1) * dstride + y] = src[y * sstride + x]; ++y; } @@ -147,40 +145,36 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_packing(const SRC *src, in + unaligned); const int rest = (h - unaligned) % pack; while (y < h - rest) { - quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + quint32 c = src[y * sstride + x]; for (int i = 1; i < pack; ++i) { - c |= qt_colorConvert<DST,SRC>(src[(y + i) * sstride + x], 0) - << (sizeof(int) * 8 / pack * i); + c |= src[(y + i) * sstride + x] << (sizeof(int) * 8 / pack * i); } *d++ = c; y += pack; } while (y < h) { - dest[(w - x - 1) * dstride + y] - = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + dest[(w - x - 1) * dstride + y] = src[y * sstride + x]; ++y; } } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_packing(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_packing(const T *src, int w, int h, int sstride, T *dest, int dstride) { - sstride /= sizeof(SRC); - dstride /= sizeof(DST); + sstride /= sizeof(T); + dstride /= sizeof(T); - const int pack = sizeof(quint32) / sizeof(DST); - const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(DST); + const int pack = sizeof(quint32) / sizeof(T); + const int unaligned = int((long(dest) & (sizeof(quint32)-1))) / sizeof(T); for (int x = 0; x < w; ++x) { int y = h - 1; for (int i = 0; i < unaligned; ++i) { - dest[x * dstride + h - y - 1] - = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + dest[x * dstride + h - y - 1] = src[y * sstride + x]; --y; } @@ -188,17 +182,15 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_packing(const SRC *src, i + unaligned); const int rest = (h - unaligned) % pack; while (y > rest) { - quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + quint32 c = src[y * sstride + x]; for (int i = 1; i < pack; ++i) { - c |= qt_colorConvert<DST,SRC>(src[(y - i) * sstride + x], 0) - << (sizeof(int) * 8 / pack * i); + c |= src[(y - i) * sstride + x] << (sizeof(int) * 8 / pack * i); } *d++ = c; y -= pack; } while (y >= 0) { - dest[x * dstride + h - y - 1] - = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + dest[x * dstride + h - y - 1] = src[y * sstride + x]; --y; } } @@ -207,17 +199,16 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_packing(const SRC *src, i #endif // QT_ROTATION_PACKING #if QT_ROTATION_ALGORITHM == QT_ROTATION_TILED -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride) { - sstride /= sizeof(SRC); - dstride /= sizeof(DST); + sstride /= sizeof(T); + dstride /= sizeof(T); - const int pack = sizeof(quint32) / sizeof(DST); + const int pack = sizeof(quint32) / sizeof(T); const int unaligned = - qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(DST)), uint(h)); + qMin(uint((quintptr(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h)); const int restX = w % tileSize; const int restY = (h - unaligned) % tileSize; const int unoptimizedY = restY % pack; @@ -230,9 +221,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled(const SRC *src, int if (unaligned) { for (int x = startx; x >= stopx; --x) { - DST *d = dest + (w - x - 1) * dstride; + T *d = dest + (w - x - 1) * dstride; for (int y = 0; y < unaligned; ++y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } @@ -244,10 +235,10 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled(const SRC *src, int for (int x = startx; x >= stopx; --x) { quint32 *d = reinterpret_cast<quint32*>(dest + (w - x - 1) * dstride + starty); for (int y = starty; y < stopy; y += pack) { - quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + quint32 c = src[y * sstride + x]; for (int i = 1; i < pack; ++i) { const int shift = (sizeof(int) * 8 / pack * i); - const DST color = qt_colorConvert<DST,SRC>(src[(y + i) * sstride + x], 0); + const T color = src[(y + i) * sstride + x]; c |= color << shift; } *d++ = c; @@ -258,19 +249,19 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled(const SRC *src, int if (unoptimizedY) { const int starty = h - unoptimizedY; for (int x = startx; x >= stopx; --x) { - DST *d = dest + (w - x - 1) * dstride + starty; + T *d = dest + (w - x - 1) * dstride + starty; for (int y = starty; y < h; ++y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled_unpacked(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest, + int dstride) { const int numTilesX = (w + tileSize - 1) / tileSize; const int numTilesY = (h + tileSize - 1) / tileSize; @@ -284,10 +275,10 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled_unpacked(const SRC * const int stopy = qMin(starty + tileSize, h); for (int x = startx; x >= stopx; --x) { - DST *d = (DST*)((char*)dest + (w - x - 1) * dstride) + starty; + T *d = (T *)((char*)dest + (w - x - 1) * dstride) + starty; const char *s = (const char*)(src + x) + starty * sstride; for (int y = starty; y < stopy; ++y) { - *d++ = qt_colorConvert<DST,SRC>(*(const SRC*)(s), 0); + *d++ = *(const T *)(s); s += sstride; } } @@ -295,17 +286,16 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_tiled_unpacked(const SRC * } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_tiled(const T *src, int w, int h, int sstride, T *dest, int dstride) { - sstride /= sizeof(SRC); - dstride /= sizeof(DST); + sstride /= sizeof(T); + dstride /= sizeof(T); - const int pack = sizeof(quint32) / sizeof(DST); + const int pack = sizeof(quint32) / sizeof(T); const int unaligned = - qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(DST)), uint(h)); + qMin(uint((long(dest) & (sizeof(quint32)-1)) / sizeof(T)), uint(h)); const int restX = w % tileSize; const int restY = (h - unaligned) % tileSize; const int unoptimizedY = restY % pack; @@ -318,9 +308,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled(const SRC *src, int if (unaligned) { for (int x = startx; x < stopx; ++x) { - DST *d = dest + x * dstride; + T *d = dest + x * dstride; for (int y = h - 1; y >= h - unaligned; --y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } @@ -333,10 +323,10 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled(const SRC *src, int quint32 *d = reinterpret_cast<quint32*>(dest + x * dstride + h - 1 - starty); for (int y = starty; y > stopy; y -= pack) { - quint32 c = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + quint32 c = src[y * sstride + x]; for (int i = 1; i < pack; ++i) { const int shift = (sizeof(int) * 8 / pack * i); - const DST color = qt_colorConvert<DST,SRC>(src[(y - i) * sstride + x], 0); + const T color = src[(y - i) * sstride + x]; c |= color << shift; } *d++ = c; @@ -346,19 +336,19 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled(const SRC *src, int if (unoptimizedY) { const int starty = unoptimizedY - 1; for (int x = startx; x < stopx; ++x) { - DST *d = dest + x * dstride + h - 1 - starty; + T *d = dest + x * dstride + h - 1 - starty; for (int y = starty; y >= 0; --y) { - *d++ = qt_colorConvert<DST,SRC>(src[y * sstride + x], 0); + *d++ = src[y * sstride + x]; } } } } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled_unpacked(const SRC *src, int w, int h, - int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_tiled_unpacked(const T *src, int w, int h, int sstride, T *dest, + int dstride) { const int numTilesX = (w + tileSize - 1) / tileSize; const int numTilesY = (h + tileSize - 1) / tileSize; @@ -372,10 +362,10 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled_unpacked(const SRC const int stopy = qMax(starty - tileSize, 0); for (int x = startx; x < stopx; ++x) { - DST *d = (DST*)((char*)dest + x * dstride) + h - 1 - starty; + T *d = (T*)((char*)dest + x * dstride) + h - 1 - starty; const char *s = (const char*)(src + x) + starty * sstride; for (int y = starty; y >= stopy; --y) { - *d++ = qt_colorConvert<DST,SRC>(*(const SRC*)s, 0); + *d++ = *(const T*)s; s -= sstride; } } @@ -385,214 +375,112 @@ Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_tiled_unpacked(const SRC #endif // QT_ROTATION_ALGORITHM -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate90_template(const SRC *src, - int srcWidth, int srcHeight, int srcStride, - DST *dest, int dstStride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate90_template(const T *src, int srcWidth, int srcHeight, int srcStride, + T *dest, int dstStride) { #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD - qt_memrotate90_cachedRead<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate90_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE - qt_memrotate90_cachedWrite<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate90_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING - qt_memrotate90_packing<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate90_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED - qt_memrotate90_tiled<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate90_tiled<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #endif } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate180_template(const SRC *src, - int w, int h, int sstride, - DST *dest, int dstride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate180_template(const T *src, int w, int h, int sstride, T *dest, int dstride) { const char *s = (const char*)(src) + (h - 1) * sstride; for (int y = h - 1; y >= 0; --y) { - DST *d = reinterpret_cast<DST*>((char *)(dest) + (h - y - 1) * dstride); - src = reinterpret_cast<const SRC*>(s); + T *d = reinterpret_cast<T*>((char *)(dest) + (h - y - 1) * dstride); + src = reinterpret_cast<const T*>(s); for (int x = w - 1; x >= 0; --x) { - d[w - x - 1] = qt_colorConvert<DST,SRC>(src[x], 0); + d[w - x - 1] = src[x]; } s -= sstride; } } -template <class DST, class SRC> -Q_STATIC_TEMPLATE_FUNCTION inline void qt_memrotate270_template(const SRC *src, - int srcWidth, int srcHeight, int srcStride, - DST *dest, int dstStride) +template <class T> +Q_STATIC_TEMPLATE_FUNCTION +inline void qt_memrotate270_template(const T *src, int srcWidth, int srcHeight, int srcStride, + T *dest, int dstStride) { #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD - qt_memrotate270_cachedRead<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate270_cachedRead<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE - qt_memrotate270_cachedWrite<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate270_cachedWrite<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING - qt_memrotate270_packing<DST,SRC>(src, srcWidth, srcHeight, srcStride, - dest, dstStride); + qt_memrotate270_packing<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED - qt_memrotate270_tiled_unpacked<DST,SRC>(src, srcWidth, srcHeight, - srcStride, - dest, dstStride); + qt_memrotate270_tiled_unpacked<T>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #endif } template <> Q_STATIC_TEMPLATE_SPECIALIZATION -inline void qt_memrotate90_template<quint24, quint24>(const quint24 *src, - int srcWidth, int srcHeight, int srcStride, - quint24 *dest, int dstStride) +inline void qt_memrotate90_template<quint24>(const quint24 *src, int srcWidth, int srcHeight, + int srcStride, quint24 *dest, int dstStride) { #if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD - qt_memrotate90_cachedRead<quint24,quint24>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); + qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE - qt_memrotate90_cachedWrite<quint24,quint24>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); + qt_memrotate90_cachedWrite<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING // packed algorithm not implemented - qt_memrotate90_cachedRead<quint24,quint24>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); + qt_memrotate90_cachedRead<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED // packed algorithm not implemented - qt_memrotate90_tiled_unpacked<quint24,quint24>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); + qt_memrotate90_tiled_unpacked<quint24>(src, srcWidth, srcHeight, srcStride, dest, dstStride); #endif } -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void qt_memrotate90_template<quint24, quint32>(const quint32 *src, - int srcWidth, int srcHeight, int srcStride, - quint24 *dest, int dstStride) -{ -#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD - qt_memrotate90_cachedRead<quint24,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE - qt_memrotate90_cachedWrite<quint24,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING - // packed algorithm not implemented - qt_memrotate90_cachedRead<quint24,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED - // packed algorithm not implemented - qt_memrotate90_tiled_unpacked<quint24,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#endif -} - -template <> -Q_STATIC_TEMPLATE_SPECIALIZATION -inline void qt_memrotate90_template<quint18, quint32>(const quint32 *src, - int srcWidth, int srcHeight, int srcStride, - quint18 *dest, int dstStride) -{ -#if QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDREAD - qt_memrotate90_cachedRead<quint18,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_CACHEDWRITE - qt_memrotate90_cachedWrite<quint18,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_PACKING - // packed algorithm not implemented - qt_memrotate90_cachedRead<quint18,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#elif QT_ROTATION_ALGORITHM == QT_ROTATION_TILED - // packed algorithm not implemented - qt_memrotate90_tiled_unpacked<quint18,quint32>(src, srcWidth, srcHeight, - srcStride, dest, dstStride); -#endif -} - -#define QT_IMPL_MEMROTATE(srctype, desttype) \ -Q_GUI_EXPORT void qt_memrotate90(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +#define QT_IMPL_MEMROTATE(type) \ +Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ qt_memrotate90_template(src, w, h, sstride, dest, dstride); \ } \ -Q_GUI_EXPORT void qt_memrotate180(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ qt_memrotate180_template(src, w, h, sstride, dest, dstride); \ } \ -Q_GUI_EXPORT void qt_memrotate270(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ qt_memrotate270_template(src, w, h, sstride, dest, dstride); \ } -#define QT_IMPL_SIMPLE_MEMROTATE(srctype, desttype) \ -Q_GUI_EXPORT void qt_memrotate90(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +#define QT_IMPL_SIMPLE_MEMROTATE(type) \ +Q_GUI_EXPORT void qt_memrotate90(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ - qt_memrotate90_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \ + qt_memrotate90_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \ } \ -Q_GUI_EXPORT void qt_memrotate180(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +Q_GUI_EXPORT void qt_memrotate180(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ qt_memrotate180_template(src, w, h, sstride, dest, dstride); \ } \ -Q_GUI_EXPORT void qt_memrotate270(const srctype *src, int w, int h, int sstride, \ - desttype *dest, int dstride) \ +Q_GUI_EXPORT void qt_memrotate270(const type *src, int w, int h, int sstride, \ + type *dest, int dstride) \ { \ - qt_memrotate270_tiled_unpacked<desttype,srctype>(src, w, h, sstride, dest, dstride); \ + qt_memrotate270_tiled_unpacked<type>(src, w, h, sstride, dest, dstride); \ } -QT_IMPL_MEMROTATE(quint32, quint32) -QT_IMPL_MEMROTATE(quint32, quint16) -QT_IMPL_MEMROTATE(quint16, quint32) -QT_IMPL_MEMROTATE(quint16, quint16) -QT_IMPL_MEMROTATE(quint24, quint24) -QT_IMPL_MEMROTATE(quint32, quint24) -QT_IMPL_MEMROTATE(quint32, quint18) -QT_IMPL_MEMROTATE(quint32, quint8) -QT_IMPL_MEMROTATE(quint16, quint8) -QT_IMPL_MEMROTATE(qrgb444, quint8) -QT_IMPL_MEMROTATE(quint8, quint8) - -#if defined(QT_QWS_ROTATE_BGR) -QT_IMPL_SIMPLE_MEMROTATE(quint16, qbgr565) -QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr565) -QT_IMPL_SIMPLE_MEMROTATE(qrgb555, qbgr555) -QT_IMPL_SIMPLE_MEMROTATE(quint32, qbgr555) -#endif - -#ifdef QT_QWS_DEPTH_GENERIC -QT_IMPL_MEMROTATE(quint32, qrgb_generic16) -QT_IMPL_MEMROTATE(quint16, qrgb_generic16) -#endif - -struct qrgb_gl_rgba -{ -public: - inline qrgb_gl_rgba(quint32 v) { - if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) - data = ((v << 16) & 0xff0000) | ((v >> 16) & 0xff) | (v & 0xff00ff00); - else - data = (v << 8) | ((v >> 24) & 0xff); - } - - inline operator quint32() const { return data; } - -private: - quint32 data; -} Q_PACKED; - -void Q_GUI_EXPORT qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, - quint32 *dest, int dstStride) -{ - qt_memrotate90_template(src, srcWidth, srcHeight, srcStride, reinterpret_cast<qrgb_gl_rgba *>(dest), dstStride); -} +QT_IMPL_MEMROTATE(quint32) +QT_IMPL_MEMROTATE(quint16) +QT_IMPL_MEMROTATE(quint24) +QT_IMPL_MEMROTATE(quint8) void qt_memrotate90_16(const uchar *srcPixels, int w, int h, int sbpl, uchar *destPixels, int dbpl) { diff --git a/src/gui/painting/qmemrotate_p.h b/src/gui/painting/qmemrotate_p.h index 4c4bc94767..a72310e330 100644 --- a/src/gui/painting/qmemrotate_p.h +++ b/src/gui/painting/qmemrotate_p.h @@ -70,37 +70,15 @@ QT_BEGIN_NAMESPACE #endif #endif -#define QT_DECL_MEMROTATE(srctype, desttype) \ - void Q_GUI_EXPORT qt_memrotate90(const srctype*, int, int, int, desttype*, int); \ - void Q_GUI_EXPORT qt_memrotate180(const srctype*, int, int, int, desttype*, int); \ - void Q_GUI_EXPORT qt_memrotate270(const srctype*, int, int, int, desttype*, int) +#define QT_DECL_MEMROTATE(type) \ + void Q_GUI_EXPORT qt_memrotate90(const type*, int, int, int, type*, int); \ + void Q_GUI_EXPORT qt_memrotate180(const type*, int, int, int, type*, int); \ + void Q_GUI_EXPORT qt_memrotate270(const type*, int, int, int, type*, int) -void Q_GUI_EXPORT qt_memrotate90(const quint32*, int, int, int, quint32*, int); -void Q_GUI_EXPORT qt_memrotate180(const quint32*, int, int, int, quint32*, int); -void Q_GUI_EXPORT qt_memrotate270(const quint32*, int, int, int, quint32*, int); - -QT_DECL_MEMROTATE(quint32, quint16); -QT_DECL_MEMROTATE(quint16, quint32); -QT_DECL_MEMROTATE(quint16, quint16); -QT_DECL_MEMROTATE(quint24, quint24); -QT_DECL_MEMROTATE(quint32, quint24); -QT_DECL_MEMROTATE(quint32, quint18); -QT_DECL_MEMROTATE(quint32, quint8); -QT_DECL_MEMROTATE(quint16, quint8); -QT_DECL_MEMROTATE(qrgb444, quint8); -QT_DECL_MEMROTATE(quint8, quint8); - -#ifdef QT_QWS_ROTATE_BGR -QT_DECL_MEMROTATE(quint16, qbgr565); -QT_DECL_MEMROTATE(quint32, qbgr565); -QT_DECL_MEMROTATE(qrgb555, qbgr555); -QT_DECL_MEMROTATE(quint32, qbgr555); -#endif - -#ifdef QT_QWS_DEPTH_GENERIC -QT_DECL_MEMROTATE(quint32, qrgb_generic16); -QT_DECL_MEMROTATE(quint16, qrgb_generic16); -#endif +QT_DECL_MEMROTATE(quint32); +QT_DECL_MEMROTATE(quint16); +QT_DECL_MEMROTATE(quint24); +QT_DECL_MEMROTATE(quint8); #undef QT_DECL_MEMROTATE |