| /**************************************************************************** |
| /**************************************************************************** |
| ** |
| ** |
| ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
| ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). |
| ** All rights reserved. |
| ** All rights reserved. |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** Contact: Nokia Corporation (qt-info@nokia.com) |
| ** |
| ** |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** This file is part of the QtGui module of the Qt Toolkit. |
| ** |
| ** |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** $QT_BEGIN_LICENSE:LGPL$ |
| ** Commercial Usage |
| ** Commercial Usage |
| ** Licensees holding valid Qt Commercial licenses may use this file in |
| ** Licensees holding valid Qt Commercial licenses may use this file in |
| ** accordance with the Qt Commercial License Agreement provided with the |
| ** accordance with the Qt Commercial License Agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and Nokia. |
| ** a written agreement between you and Nokia. |
| ** |
| ** |
| ** GNU Lesser General Public License Usage |
| ** GNU Lesser General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** Alternatively, this file may be used under the terms of the GNU Lesser |
| ** General Public License version 2.1 as published by the Free Software |
| ** General Public License version 2.1 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.LGPL included in the |
| ** Foundation and appearing in the file LICENSE.LGPL included in the |
| ** packaging of this file. Please review the following information to |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU Lesser General Public License version 2.1 requirements |
| ** ensure the GNU Lesser General Public License version 2.1 requirements |
| ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| ** |
| ** |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** In addition, as a special exception, Nokia gives you certain additional |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** rights. These rights are described in the Nokia Qt LGPL Exception |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| ** |
| ** |
| ** GNU General Public License Usage |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3.0 as published by the Free Software |
| ** General Public License version 3.0 as published by the Free Software |
| ** Foundation and appearing in the file LICENSE.GPL included in the |
| ** Foundation and appearing in the file LICENSE.GPL included in the |
| ** packaging of this file. Please review the following information to |
| ** packaging of this file. Please review the following information to |
| ** ensure the GNU General Public License version 3.0 requirements will be |
| ** ensure the GNU General Public License version 3.0 requirements will be |
| ** met: http://www.gnu.org/copyleft/gpl.html. |
| ** met: http://www.gnu.org/copyleft/gpl.html. |
| ** |
| ** |
| ** If you have questions regarding the use of this file, please contact |
| ** If you have questions regarding the use of this file, please contact |
| ** Nokia at qt-info@nokia.com. |
| ** Nokia at qt-info@nokia.com. |
| ** $QT_END_LICENSE$ |
| ** $QT_END_LICENSE$ |
| ** |
| ** |
| ****************************************************************************/ |
| ****************************************************************************/ |
| |
| |
| #include <private/qdrawhelper_p.h> |
| #include <private/qdrawhelper_p.h> |
| #include <private/qpaintengine_raster_p.h> |
| #include <private/qpaintengine_raster_p.h> |
| #include <private/qpainter_p.h> |
| #include <private/qpainter_p.h> |
| #include <private/qdrawhelper_x86_p.h> |
| #include <private/qdrawhelper_x86_p.h> |
| #include <private/qdrawhelper_armv6_p.h> |
| #include <private/qdrawhelper_arm_simd_p.h> |
| #include <private/qdrawhelper_neon_p.h> |
| #include <private/qdrawhelper_neon_p.h> |
| #include <private/qmath_p.h> |
| #include <private/qmath_p.h> |
| #include <qmath.h> |
| #include <qmath.h> |
| |
| |
| QT_BEGIN_NAMESPACE |
| QT_BEGIN_NAMESPACE |
| |
| |
| |
| |
| #define MASK(src, a) src = BYTE_MUL(src, a) |
| #define MASK(src, a) src = BYTE_MUL(src, a) |
| |
| |
| #if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8 |
| #if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8 |
| #define Q_IRIX_GCC3_3_WORKAROUND |
| #define Q_IRIX_GCC3_3_WORKAROUND |
| // |
| // |
| // work around http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14484 |
| // work around http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14484 |
| // |
| // |
| static uint gccBug(uint value) __attribute__((noinline)); |
| static uint gccBug(uint value) __attribute__((noinline)); |
| static uint gccBug(uint value) |
| static uint gccBug(uint value) |
| { |
| { |
| return value; |
| return value; |
| } |
| } |
| #endif |
| #endif |
| |
| |
| /* |
| /* |
| constants and structures |
| constants and structures |
| */ |
| */ |
| |
| |
| enum { |
| enum { |
| fixed_scale = 1 << 16, |
| fixed_scale = 1 << 16, |
| half_point = 1 << 15 |
| half_point = 1 << 15 |
| }; |
| }; |
| static const int buffer_size = 2048; |
| static const int buffer_size = 2048; |
| |
| |
| struct LinearGradientValues |
| struct LinearGradientValues |
| { |
| { |
| qreal dx; |
| qreal dx; |
| qreal dy; |
| qreal dy; |
| qreal l; |
| qreal l; |
| qreal off; |
| qreal off; |
| }; |
| }; |
| |
| |
| struct RadialGradientValues |
| struct RadialGradientValues |
| { |
| { |
| qreal dx; |
| qreal dx; |
| qreal dy; |
| qreal dy; |
| qreal a; |
| qreal a; |
| }; |
| }; |
| |
| |
| struct Operator; |
| struct Operator; |
| typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); |
| typedef uint* (QT_FASTCALL *DestFetchProc)(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length); |
| typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); |
| typedef void (QT_FASTCALL *DestStoreProc)(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length); |
| typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); |
| typedef const uint* (QT_FASTCALL *SourceFetchProc)(uint *buffer, const Operator *o, const QSpanData *data, int y, int x, int length); |
| |
| |
| |
| |
| struct Operator |
| struct Operator |
| { |
| { |
| QPainter::CompositionMode mode; |
| QPainter::CompositionMode mode; |
| DestFetchProc dest_fetch; |
| DestFetchProc dest_fetch; |
| DestStoreProc dest_store; |
| DestStoreProc dest_store; |
| SourceFetchProc src_fetch; |
| SourceFetchProc src_fetch; |
| CompositionFunctionSolid funcSolid; |
| CompositionFunctionSolid funcSolid; |
| CompositionFunction func; |
| CompositionFunction func; |
| union { |
| union { |
| LinearGradientValues linear; |
| LinearGradientValues linear; |
| RadialGradientValues radial; |
| RadialGradientValues radial; |
| // TextureValues texture; |
| // TextureValues texture; |
| }; |
| }; |
| }; |
| }; |
| |
| |
| /* |
| /* |
| Destination fetch. This is simple as we don't have to do bounds checks or |
| Destination fetch. This is simple as we don't have to do bounds checks or |
| transformations |
| transformations |
| */ |
| */ |
| |
| |
| static uint * QT_FASTCALL destFetchMono(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| static uint * QT_FASTCALL destFetchMono(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| { |
| { |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uint *start = buffer; |
| uint *start = buffer; |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| while (buffer < end) { |
| while (buffer < end) { |
| *buffer = data[x>>3] & (0x80 >> (x & 7)) ? rasterBuffer->destColor1 : rasterBuffer->destColor0; |
| *buffer = data[x>>3] & (0x80 >> (x & 7)) ? rasterBuffer->destColor1 : rasterBuffer->destColor0; |
| ++buffer; |
| ++buffer; |
| ++x; |
| ++x; |
| } |
| } |
| return start; |
| return start; |
| } |
| } |
| |
| |
| static uint * QT_FASTCALL destFetchMonoLsb(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| static uint * QT_FASTCALL destFetchMonoLsb(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| { |
| { |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uint *start = buffer; |
| uint *start = buffer; |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| while (buffer < end) { |
| while (buffer < end) { |
| *buffer = data[x>>3] & (0x1 << (x & 7)) ? rasterBuffer->destColor1 : rasterBuffer->destColor0; |
| *buffer = data[x>>3] & (0x1 << (x & 7)) ? rasterBuffer->destColor1 : rasterBuffer->destColor0; |
| ++buffer; |
| ++buffer; |
| ++x; |
| ++x; |
| } |
| } |
| return start; |
| return start; |
| } |
| } |
| |
| |
| static uint * QT_FASTCALL destFetchARGB32(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| static uint * QT_FASTCALL destFetchARGB32(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| { |
| { |
| const uint *data = (const uint *)rasterBuffer->scanLine(y) + x; |
| const uint *data = (const uint *)rasterBuffer->scanLine(y) + x; |
| for (int i = 0; i < length; ++i) |
| for (int i = 0; i < length; ++i) |
| buffer[i] = PREMUL(data[i]); |
| buffer[i] = PREMUL(data[i]); |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| static uint * QT_FASTCALL destFetchARGB32P(uint *, QRasterBuffer *rasterBuffer, int x, int y, int) |
| static uint * QT_FASTCALL destFetchARGB32P(uint *, QRasterBuffer *rasterBuffer, int x, int y, int) |
| { |
| { |
| return (uint *)rasterBuffer->scanLine(y) + x; |
| return (uint *)rasterBuffer->scanLine(y) + x; |
| } |
| } |
| |
| |
| static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuffer, int x, int y, int length) |
| { |
| { |
| const ushort *data = (const ushort *)rasterBuffer->scanLine(y) + x; |
| const ushort *data = (const ushort *)rasterBuffer->scanLine(y) + x; |
| for (int i = 0; i < length; ++i) |
| for (int i = 0; i < length; ++i) |
| buffer[i] = qConvertRgb16To32(data[i]); |
| buffer[i] = qConvertRgb16To32(data[i]); |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| template <class DST> |
| template <class DST> |
| Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, |
| Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer, |
| int x, int y, int length) |
| int x, int y, int length) |
| { |
| { |
| const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; |
| const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; |
| quint32 *dest = reinterpret_cast<quint32*>(buffer); |
| quint32 *dest = reinterpret_cast<quint32*>(buffer); |
| while (length--) |
| while (length--) |
| *dest++ = *src++; |
| *dest++ = *src++; |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| # define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg> |
| # define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg> |
| |
| |
| static DestFetchProc destFetchProc[QImage::NImageFormats] = |
| static DestFetchProc destFetchProc[QImage::NImageFormats] = |
| { |
| { |
| 0, // Format_Invalid |
| 0, // Format_Invalid |
| destFetchMono, // Format_Mono, |
| destFetchMono, // Format_Mono, |
| destFetchMonoLsb, // Format_MonoLSB |
| destFetchMonoLsb, // Format_MonoLSB |
| 0, // Format_Indexed8 |
| 0, // Format_Indexed8 |
| destFetchARGB32P, // Format_RGB32 |
| destFetchARGB32P, // Format_RGB32 |
| destFetchARGB32, // Format_ARGB32, |
| destFetchARGB32, // Format_ARGB32, |
| destFetchARGB32P, // Format_ARGB32_Premultiplied |
| destFetchARGB32P, // Format_ARGB32_Premultiplied |
| destFetchRGB16, // Format_RGB16 |
| destFetchRGB16, // Format_RGB16 |
| SPANFUNC_POINTER_DESTFETCH(qargb8565), // Format_ARGB8565_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qargb8565), // Format_ARGB8565_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qrgb666), // Format_RGB666 |
| SPANFUNC_POINTER_DESTFETCH(qrgb666), // Format_RGB666 |
| SPANFUNC_POINTER_DESTFETCH(qargb6666), // Format_ARGB6666_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qargb6666), // Format_ARGB6666_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qrgb555), // Format_RGB555 |
| SPANFUNC_POINTER_DESTFETCH(qrgb555), // Format_RGB555 |
| SPANFUNC_POINTER_DESTFETCH(qargb8555), // Format_ARGB8555_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qargb8555), // Format_ARGB8555_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qrgb888), // Format_RGB888 |
| SPANFUNC_POINTER_DESTFETCH(qrgb888), // Format_RGB888 |
| SPANFUNC_POINTER_DESTFETCH(qrgb444), // Format_RGB444 |
| SPANFUNC_POINTER_DESTFETCH(qrgb444), // Format_RGB444 |
| SPANFUNC_POINTER_DESTFETCH(qargb4444) // Format_ARGB4444_Premultiplied |
| SPANFUNC_POINTER_DESTFETCH(qargb4444) // Format_ARGB4444_Premultiplied |
| }; |
| }; |
| |
| |
| /* |
| /* |
| Returns the color in the mono destination color table |
| Returns the color in the mono destination color table |
| that is the "nearest" to /color/. |
| that is the "nearest" to /color/. |
| */ |
| */ |
| static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf) |
| static inline QRgb findNearestColor(QRgb color, QRasterBuffer *rbuf) |
| { |
| { |
| QRgb color_0 = PREMUL(rbuf->destColor0); |
| QRgb color_0 = PREMUL(rbuf->destColor0); |
| QRgb color_1 = PREMUL(rbuf->destColor1); |
| QRgb color_1 = PREMUL(rbuf->destColor1); |
| color = PREMUL(color); |
| color = PREMUL(color); |
| |
| |
| int r = qRed(color); |
| int r = qRed(color); |
| int g = qGreen(color); |
| int g = qGreen(color); |
| int b = qBlue(color); |
| int b = qBlue(color); |
| int rx, gx, bx; |
| int rx, gx, bx; |
| int dist_0, dist_1; |
| int dist_0, dist_1; |
| |
| |
| rx = r - qRed(color_0); |
| rx = r - qRed(color_0); |
| gx = g - qGreen(color_0); |
| gx = g - qGreen(color_0); |
| bx = b - qBlue(color_0); |
| bx = b - qBlue(color_0); |
| dist_0 = rx*rx + gx*gx + bx*bx; |
| dist_0 = rx*rx + gx*gx + bx*bx; |
| |
| |
| rx = r - qRed(color_1); |
| rx = r - qRed(color_1); |
| gx = g - qGreen(color_1); |
| gx = g - qGreen(color_1); |
| bx = b - qBlue(color_1); |
| bx = b - qBlue(color_1); |
| dist_1 = rx*rx + gx*gx + bx*bx; |
| dist_1 = rx*rx + gx*gx + bx*bx; |
| |
| |
| if (dist_0 < dist_1) |
| if (dist_0 < dist_1) |
| return color_0; |
| return color_0; |
| return color_1; |
| return color_1; |
| } |
| } |
| |
| |
| /* |
| /* |
| Destination store. |
| Destination store. |
| */ |
| */ |
| |
| |
| static void QT_FASTCALL destStoreMono(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| static void QT_FASTCALL destStoreMono(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| { |
| { |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| if (rasterBuffer->monoDestinationWithClut) { |
| if (rasterBuffer->monoDestinationWithClut) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| if (buffer[i] == rasterBuffer->destColor0) { |
| if (buffer[i] == rasterBuffer->destColor0) { |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| } else if (buffer[i] == rasterBuffer->destColor1) { |
| } else if (buffer[i] == rasterBuffer->destColor1) { |
| data[x >> 3] |= 0x80 >> (x & 7); |
| data[x >> 3] |= 0x80 >> (x & 7); |
| } else if (findNearestColor(buffer[i], rasterBuffer) == rasterBuffer->destColor0) { |
| } else if (findNearestColor(buffer[i], rasterBuffer) == rasterBuffer->destColor0) { |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| } else { |
| } else { |
| data[x >> 3] |= 0x80 >> (x & 7); |
| data[x >> 3] |= 0x80 >> (x & 7); |
| } |
| } |
| ++x; |
| ++x; |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| if (qGray(buffer[i]) < int(qt_bayer_matrix[y & 15][x & 15])) |
| if (qGray(buffer[i]) < int(qt_bayer_matrix[y & 15][x & 15])) |
| data[x >> 3] |= 0x80 >> (x & 7); |
| data[x >> 3] |= 0x80 >> (x & 7); |
| else |
| else |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| data[x >> 3] &= ~(0x80 >> (x & 7)); |
| ++x; |
| ++x; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void QT_FASTCALL destStoreMonoLsb(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| static void QT_FASTCALL destStoreMonoLsb(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| { |
| { |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| uchar *data = (uchar *)rasterBuffer->scanLine(y); |
| if (rasterBuffer->monoDestinationWithClut) { |
| if (rasterBuffer->monoDestinationWithClut) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| if (buffer[i] == rasterBuffer->destColor0) { |
| if (buffer[i] == rasterBuffer->destColor0) { |
| data[x >> 3] &= ~(1 << (x & 7)); |
| data[x >> 3] &= ~(1 << (x & 7)); |
| } else if (buffer[i] == rasterBuffer->destColor1) { |
| } else if (buffer[i] == rasterBuffer->destColor1) { |
| data[x >> 3] |= 1 << (x & 7); |
| data[x >> 3] |= 1 << (x & 7); |
| } else if (findNearestColor(buffer[i], rasterBuffer) == rasterBuffer->destColor0) { |
| } else if (findNearestColor(buffer[i], rasterBuffer) == rasterBuffer->destColor0) { |
| data[x >> 3] &= ~(1 << (x & 7)); |
| data[x >> 3] &= ~(1 << (x & 7)); |
| } else { |
| } else { |
| data[x >> 3] |= 1 << (x & 7); |
| data[x >> 3] |= 1 << (x & 7); |
| } |
| } |
| ++x; |
| ++x; |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| if (qGray(buffer[i]) < int(qt_bayer_matrix[y & 15][x & 15])) |
| if (qGray(buffer[i]) < int(qt_bayer_matrix[y & 15][x & 15])) |
| data[x >> 3] |= 1 << (x & 7); |
| data[x >> 3] |= 1 << (x & 7); |
| else |
| else |
| data[x >> 3] &= ~(1 << (x & 7)); |
| data[x >> 3] &= ~(1 << (x & 7)); |
| ++x; |
| ++x; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void QT_FASTCALL destStoreARGB32(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| static void QT_FASTCALL destStoreARGB32(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| { |
| { |
| uint *data = (uint *)rasterBuffer->scanLine(y) + x; |
| uint *data = (uint *)rasterBuffer->scanLine(y) + x; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| int p = buffer[i]; |
| int p = buffer[i]; |
| int alpha = qAlpha(p); |
| int alpha = qAlpha(p); |
| if (alpha == 255) |
| if (alpha == 255) |
| data[i] = p; |
| data[i] = p; |
| else if (alpha == 0) |
| else if (alpha == 0) |
| data[i] = 0; |
| data[i] = 0; |
| else { |
| else { |
| int inv_alpha = 0xff0000/qAlpha(buffer[i]); |
| int inv_alpha = 0xff0000/qAlpha(buffer[i]); |
| data[i] = (p & 0xff000000) |
| data[i] = (p & 0xff000000) |
| | ((qRed(p)*inv_alpha) & 0xff0000) |
| | ((qRed(p)*inv_alpha) & 0xff0000) |
| | (((qGreen(p)*inv_alpha) >> 8) & 0xff00) |
| | (((qGreen(p)*inv_alpha) >> 8) & 0xff00) |
| | ((qBlue(p)*inv_alpha) >> 16); |
| | ((qBlue(p)*inv_alpha) >> 16); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y, const uint *buffer, int length) |
| { |
| { |
| quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x; |
| quint16 *data = (quint16*)rasterBuffer->scanLine(y) + x; |
| qt_memconvert<quint16, quint32>(data, buffer, length); |
| qt_memconvert<quint16, quint32>(data, buffer, length); |
| } |
| } |
| |
| |
| template <class DST> |
| template <class DST> |
| Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, |
| Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer, |
| int x, int y, |
| int x, int y, |
| const uint *buffer, int length) |
| const uint *buffer, int length) |
| { |
| { |
| DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; |
| DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x; |
| const quint32p *src = reinterpret_cast<const quint32p*>(buffer); |
| const quint32p *src = reinterpret_cast<const quint32p*>(buffer); |
| while (length--) |
| while (length--) |
| *dest++ = DST(*src++); |
| *dest++ = DST(*src++); |
| } |
| } |
| |
| |
| # define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST> |
| # define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST> |
| |
| |
| static DestStoreProc destStoreProc[QImage::NImageFormats] = |
| static DestStoreProc destStoreProc[QImage::NImageFormats] = |
| { |
| { |
| 0, // Format_Invalid |
| 0, // Format_Invalid |
| destStoreMono, // Format_Mono, |
| destStoreMono, // Format_Mono, |
| destStoreMonoLsb, // Format_MonoLSB |
| destStoreMonoLsb, // Format_MonoLSB |
| 0, // Format_Indexed8 |
| 0, // Format_Indexed8 |
| 0, // Format_RGB32 |
| 0, // Format_RGB32 |
| destStoreARGB32, // Format_ARGB32, |
| destStoreARGB32, // Format_ARGB32, |
| 0, // Format_ARGB32_Premultiplied |
| 0, // Format_ARGB32_Premultiplied |
| destStoreRGB16, // Format_RGB16 |
| destStoreRGB16, // Format_RGB16 |
| SPANFUNC_POINTER_DESTSTORE(qargb8565), // Format_ARGB8565_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qargb8565), // Format_ARGB8565_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qrgb666), // Format_RGB666 |
| SPANFUNC_POINTER_DESTSTORE(qrgb666), // Format_RGB666 |
| SPANFUNC_POINTER_DESTSTORE(qargb6666), // Format_ARGB6666_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qargb6666), // Format_ARGB6666_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qrgb555), // Format_RGB555 |
| SPANFUNC_POINTER_DESTSTORE(qrgb555), // Format_RGB555 |
| SPANFUNC_POINTER_DESTSTORE(qargb8555), // Format_ARGB8555_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qargb8555), // Format_ARGB8555_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qrgb888), // Format_RGB888 |
| SPANFUNC_POINTER_DESTSTORE(qrgb888), // Format_RGB888 |
| SPANFUNC_POINTER_DESTSTORE(qrgb444), // Format_RGB444 |
| SPANFUNC_POINTER_DESTSTORE(qrgb444), // Format_RGB444 |
| SPANFUNC_POINTER_DESTSTORE(qargb4444) // Format_ARGB4444_Premultiplied |
| SPANFUNC_POINTER_DESTSTORE(qargb4444) // Format_ARGB4444_Premultiplied |
| }; |
| }; |
| |
| |
| /* |
| /* |
| Source fetches |
| Source fetches |
| |
| |
| This is a bit more complicated, as we need several fetch routines for every surface type |
| This is a bit more complicated, as we need several fetch routines for every surface type |
| |
| |
| We need 5 fetch methods per surface type: |
| We need 5 fetch methods per surface type: |
| untransformed |
| untransformed |
| transformed (tiled and not tiled) |
| transformed (tiled and not tiled) |
| transformed bilinear (tiled and not tiled) |
| transformed bilinear (tiled and not tiled) |
| |
| |
| We don't need bounds checks for untransformed, but we need them for the other ones. |
| We don't need bounds checks for untransformed, but we need them for the other ones. |
| |
| |
| The generic implementation does pixel by pixel fetches |
| The generic implementation does pixel by pixel fetches |
| */ |
| */ |
| |
| |
| template <QImage::Format format> |
| template <QImage::Format format> |
| Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb); |
| Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb); |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine, |
| int x, const QVector<QRgb> *rgb) |
| int x, const QVector<QRgb> *rgb) |
| { |
| { |
| bool pixel = scanLine[x>>3] & (0x80 >> (x & 7)); |
| bool pixel = scanLine[x>>3] & (0x80 >> (x & 7)); |
| if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); |
| if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); |
| return pixel ? 0xff000000 : 0xffffffff; |
| return pixel ? 0xff000000 : 0xffffffff; |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine, |
| int x, const QVector<QRgb> *rgb) |
| int x, const QVector<QRgb> *rgb) |
| { |
| { |
| bool pixel = scanLine[x>>3] & (0x1 << (x & 7)); |
| bool pixel = scanLine[x>>3] & (0x1 << (x & 7)); |
| if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); |
| if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0)); |
| return pixel ? 0xff000000 : 0xffffffff; |
| return pixel ? 0xff000000 : 0xffffffff; |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine, |
| int x, const QVector<QRgb> *rgb) |
| int x, const QVector<QRgb> *rgb) |
| { |
| { |
| return PREMUL(rgb->at(scanLine[x])); |
| return PREMUL(rgb->at(scanLine[x])); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine, |
| int x, const QVector<QRgb> *) |
| int x, const QVector<QRgb> *) |
| { |
| { |
| return PREMUL(((const uint *)scanLine)[x]); |
| return PREMUL(((const uint *)scanLine)[x]); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine, |
| int x, const QVector<QRgb> *) |
| int x, const QVector<QRgb> *) |
| { |
| { |
| return ((const uint *)scanLine)[x]; |
| return ((const uint *)scanLine)[x]; |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine, |
| int x, const QVector<QRgb> *) |
| int x, const QVector<QRgb> *) |
| { |
| { |
| return qConvertRgb16To32(((const ushort *)scanLine)[x]); |
| return qConvertRgb16To32(((const ushort *)scanLine)[x]); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x]; |
| const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qargb8565>(color, 0); |
| return qt_colorConvert<quint32, qargb8565>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x]; |
| const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qrgb666>(color, 0); |
| return qt_colorConvert<quint32, qrgb666>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x]; |
| const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qargb6666>(color, 0); |
| return qt_colorConvert<quint32, qargb6666>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x]; |
| const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qrgb555>(color, 0); |
| return qt_colorConvert<quint32, qrgb555>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x]; |
| const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qargb8555>(color, 0); |
| return qt_colorConvert<quint32, qargb8555>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x]; |
| const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qrgb888>(color, 0); |
| return qt_colorConvert<quint32, qrgb888>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x]; |
| const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qrgb444>(color, 0); |
| return qt_colorConvert<quint32, qrgb444>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine, |
| int x, |
| int x, |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x]; |
| const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x]; |
| return qt_colorConvert<quint32, qargb4444>(color, 0); |
| return qt_colorConvert<quint32, qargb4444>(color, 0); |
| } |
| } |
| |
| |
| template<> |
| template<> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *, |
| uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *, |
| int , |
| int , |
| const QVector<QRgb> *) |
| const QVector<QRgb> *) |
| { |
| { |
| return 0; |
| return 0; |
| } |
| } |
| |
| |
| typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *); |
| typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *); |
| |
| |
| #define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg> |
| #define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg> |
| |
| |
| |
| |
| static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] = |
| static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] = |
| { |
| { |
| 0, |
| 0, |
| SPANFUNC_POINTER_FETCHPIXEL(Format_Mono), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_Mono), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_MonoLSB), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_MonoLSB), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_Indexed8), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_Indexed8), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB32_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB16), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB16), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8565_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8565_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB666), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB666), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB6666_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB6666_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB555), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB555), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8555_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB8555_Premultiplied), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB888), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB888), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB444), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_RGB444), |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB4444_Premultiplied) |
| SPANFUNC_POINTER_FETCHPIXEL(Format_ARGB4444_Premultiplied) |
| }; |
| }; |
| |
| |
| enum TextureBlendType { |
| enum TextureBlendType { |
| BlendUntransformed, |
| BlendUntransformed, |
| BlendTiled, |
| BlendTiled, |
| BlendTransformed, |
| BlendTransformed, |
| BlendTransformedTiled, |
| BlendTransformedTiled, |
| BlendTransformedBilinear, |
| BlendTransformedBilinear, |
| BlendTransformedBilinearTiled, |
| BlendTransformedBilinearTiled, |
| NBlendTypes |
| NBlendTypes |
| }; |
| }; |
| |
| |
| template <QImage::Format format> |
| template <QImage::Format format> |
| Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data, |
| Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| const uchar *scanLine = data->texture.scanLine(y); |
| const uchar *scanLine = data->texture.scanLine(y); |
| for (int i = 0; i < length; ++i) |
| for (int i = 0; i < length; ++i) |
| buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable); |
| buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable); |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL |
| Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL |
| qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *, |
| qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *, |
| const QSpanData *data, |
| const QSpanData *data, |
| int y, int x, int) |
| int y, int x, int) |
| { |
| { |
| const uchar *scanLine = data->texture.scanLine(y); |
| const uchar *scanLine = data->texture.scanLine(y); |
| return ((const uint *)scanLine) + x; |
| return ((const uint *)scanLine) + x; |
| } |
| } |
| |
| |
| template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ |
| template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */ |
| Q_STATIC_TEMPLATE_FUNCTION |
| Q_STATIC_TEMPLATE_FUNCTION |
| const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, |
| const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| FetchPixelProc fetch = fetchPixelProc[data->texture.format]; |
| FetchPixelProc fetch = fetchPixelProc[data->texture.format]; |
| |
| |
| int image_width = data->texture.width; |
| int image_width = data->texture.width; |
| int image_height = data->texture.height; |
| int image_height = data->texture.height; |
| |
| |
| const qreal cx = x + 0.5; |
| const qreal cx = x + 0.5; |
| const qreal cy = y + 0.5; |
| const qreal cy = y + 0.5; |
| |
| |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| uint *b = buffer; |
| uint *b = buffer; |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| int fx = int((data->m21 * cy |
| int fx = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int fy = int((data->m22 * cy |
| int fy = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| |
| |
| while (b < end) { |
| while (b < end) { |
| int px = fx >> 16; |
| int px = fx >> 16; |
| int py = fy >> 16; |
| int py = fy >> 16; |
| |
| |
| if (blendType == BlendTransformedTiled) { |
| if (blendType == BlendTransformedTiled) { |
| px %= image_width; |
| px %= image_width; |
| py %= image_height; |
| py %= image_height; |
| if (px < 0) px += image_width; |
| if (px < 0) px += image_width; |
| if (py < 0) py += image_height; |
| if (py < 0) py += image_height; |
| |
| |
| const uchar *scanLine = data->texture.scanLine(py); |
| const uchar *scanLine = data->texture.scanLine(py); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| } else { |
| } else { |
| if ((px < 0) || (px >= image_width) |
| if ((px < 0) || (px >= image_width) |
| || (py < 0) || (py >= image_height)) { |
| || (py < 0) || (py >= image_height)) { |
| *b = uint(0); |
| *b = uint(0); |
| } else { |
| } else { |
| const uchar *scanLine = data->texture.scanLine(py); |
| const uchar *scanLine = data->texture.scanLine(py); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| } |
| } |
| } |
| } |
| fx += fdx; |
| fx += fdx; |
| fy += fdy; |
| fy += fdy; |
| ++b; |
| ++b; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| |
| |
| qreal fx = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal fx = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal fy = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal fy = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal fw = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal fw = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = fw == 0 ? 1 : 1 / fw; |
| const qreal iw = fw == 0 ? 1 : 1 / fw; |
| const qreal tx = fx * iw; |
| const qreal tx = fx * iw; |
| const qreal ty = fy * iw; |
| const qreal ty = fy * iw; |
| int px = int(tx) - (tx < 0); |
| int px = int(tx) - (tx < 0); |
| int py = int(ty) - (ty < 0); |
| int py = int(ty) - (ty < 0); |
| |
| |
| if (blendType == BlendTransformedTiled) { |
| if (blendType == BlendTransformedTiled) { |
| px %= image_width; |
| px %= image_width; |
| py %= image_height; |
| py %= image_height; |
| if (px < 0) px += image_width; |
| if (px < 0) px += image_width; |
| if (py < 0) py += image_height; |
| if (py < 0) py += image_height; |
| |
| |
| const uchar *scanLine = data->texture.scanLine(py); |
| const uchar *scanLine = data->texture.scanLine(py); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| } else { |
| } else { |
| if ((px < 0) || (px >= image_width) |
| if ((px < 0) || (px >= image_width) |
| || (py < 0) || (py >= image_height)) { |
| || (py < 0) || (py >= image_height)) { |
| *b = uint(0); |
| *b = uint(0); |
| } else { |
| } else { |
| const uchar *scanLine = data->texture.scanLine(py); |
| const uchar *scanLine = data->texture.scanLine(py); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| *b = fetch(scanLine, px, data->texture.colorTable); |
| } |
| } |
| } |
| } |
| fx += fdx; |
| fx += fdx; |
| fy += fdy; |
| fy += fdy; |
| fw += fdw; |
| fw += fdw; |
| //force increment to avoid /0 |
| //force increment to avoid /0 |
| if (!fw) { |
| if (!fw) { |
| fw += fdw; |
| fw += fdw; |
| } |
| } |
| ++b; |
| ++b; |
| } |
| } |
| } |
| } |
| |
| |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| /** \internal |
| /** \internal |
| interpolate 4 argb pixels with the distx and disty factor. |
| interpolate 4 argb pixels with the distx and disty factor. |
| distx and disty bust be between 0 and 16 |
| distx and disty bust be between 0 and 16 |
| */ |
| */ |
| static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty) |
| static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, int distx, int disty) |
| { |
| { |
| uint distxy = distx * disty; |
| uint distxy = distx * disty; |
| //idistx * disty = (16-distx) * disty = 16*disty - distxy |
| //idistx * disty = (16-distx) * disty = 16*disty - distxy |
| //idistx * idisty = (16-distx) * (16-disty) = 16*16 - 16*distx -16*dity + distxy |
| //idistx * idisty = (16-distx) * (16-disty) = 16*16 - 16*distx -16*dity + distxy |
| uint tlrb = (tl & 0x00ff00ff) * (16*16 - 16*distx - 16*disty + distxy); |
| uint tlrb = (tl & 0x00ff00ff) * (16*16 - 16*distx - 16*disty + distxy); |
| uint tlag = ((tl & 0xff00ff00) >> 8) * (16*16 - 16*distx - 16*disty + distxy); |
| uint tlag = ((tl & 0xff00ff00) >> 8) * (16*16 - 16*distx - 16*disty + distxy); |
| uint trrb = ((tr & 0x00ff00ff) * (distx*16 - distxy)); |
| uint trrb = ((tr & 0x00ff00ff) * (distx*16 - distxy)); |
| uint trag = (((tr & 0xff00ff00) >> 8) * (distx*16 - distxy)); |
| uint trag = (((tr & 0xff00ff00) >> 8) * (distx*16 - distxy)); |
| uint blrb = ((bl & 0x00ff00ff) * (disty*16 - distxy)); |
| uint blrb = ((bl & 0x00ff00ff) * (disty*16 - distxy)); |
| uint blag = (((bl & 0xff00ff00) >> 8) * (disty*16 - distxy)); |
| uint blag = (((bl & 0xff00ff00) >> 8) * (disty*16 - distxy)); |
| uint brrb = ((br & 0x00ff00ff) * (distxy)); |
| uint brrb = ((br & 0x00ff00ff) * (distxy)); |
| uint brag = (((br & 0xff00ff00) >> 8) * (distxy)); |
| uint brag = (((br & 0xff00ff00) >> 8) * (distxy)); |
| return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00); |
| return (((tlrb + trrb + blrb + brrb) >> 8) & 0x00ff00ff) | ((tlag + trag + blag + brag) & 0xff00ff00); |
| } |
| } |
| |
| |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| #define interpolate_4_pixels_16_sse2(tl, tr, bl, br, distx, disty, colorMask, v_256, b) \ |
| #define interpolate_4_pixels_16_sse2(tl, tr, bl, br, distx, disty, colorMask, v_256, b) \ |
| { \ |
| { \ |
| const __m128i dxdy = _mm_mullo_epi16 (distx, disty); \ |
| const __m128i dxdy = _mm_mullo_epi16 (distx, disty); \ |
| const __m128i distx_ = _mm_slli_epi16(distx, 4); \ |
| const __m128i distx_ = _mm_slli_epi16(distx, 4); \ |
| const __m128i disty_ = _mm_slli_epi16(disty, 4); \ |
| const __m128i disty_ = _mm_slli_epi16(disty, 4); \ |
| const __m128i idxidy = _mm_add_epi16(dxdy, _mm_sub_epi16(v_256, _mm_add_epi16(distx_, disty_))); \ |
| const __m128i idxidy = _mm_add_epi16(dxdy, _mm_sub_epi16(v_256, _mm_add_epi16(distx_, disty_))); \ |
| const __m128i dxidy = _mm_sub_epi16(distx_, dxdy); \ |
| const __m128i dxidy = _mm_sub_epi16(distx_, dxdy); \ |
| const __m128i idxdy = _mm_sub_epi16(disty_, dxdy); \ |
| const __m128i idxdy = _mm_sub_epi16(disty_, dxdy); \ |
| \ |
| \ |
| __m128i tlAG = _mm_srli_epi16(tl, 8); \ |
| __m128i tlAG = _mm_srli_epi16(tl, 8); \ |
| __m128i tlRB = _mm_and_si128(tl, colorMask); \ |
| __m128i tlRB = _mm_and_si128(tl, colorMask); \ |
| __m128i trAG = _mm_srli_epi16(tr, 8); \ |
| __m128i trAG = _mm_srli_epi16(tr, 8); \ |
| __m128i trRB = _mm_and_si128(tr, colorMask); \ |
| __m128i trRB = _mm_and_si128(tr, colorMask); \ |
| __m128i blAG = _mm_srli_epi16(bl, 8); \ |
| __m128i blAG = _mm_srli_epi16(bl, 8); \ |
| __m128i blRB = _mm_and_si128(bl, colorMask); \ |
| __m128i blRB = _mm_and_si128(bl, colorMask); \ |
| __m128i brAG = _mm_srli_epi16(br, 8); \ |
| __m128i brAG = _mm_srli_epi16(br, 8); \ |
| __m128i brRB = _mm_and_si128(br, colorMask); \ |
| __m128i brRB = _mm_and_si128(br, colorMask); \ |
| \ |
| \ |
| tlAG = _mm_mullo_epi16(tlAG, idxidy); \ |
| tlAG = _mm_mullo_epi16(tlAG, idxidy); \ |
| tlRB = _mm_mullo_epi16(tlRB, idxidy); \ |
| tlRB = _mm_mullo_epi16(tlRB, idxidy); \ |
| trAG = _mm_mullo_epi16(trAG, dxidy); \ |
| trAG = _mm_mullo_epi16(trAG, dxidy); \ |
| trRB = _mm_mullo_epi16(trRB, dxidy); \ |
| trRB = _mm_mullo_epi16(trRB, dxidy); \ |
| blAG = _mm_mullo_epi16(blAG, idxdy); \ |
| blAG = _mm_mullo_epi16(blAG, idxdy); \ |
| blRB = _mm_mullo_epi16(blRB, idxdy); \ |
| blRB = _mm_mullo_epi16(blRB, idxdy); \ |
| brAG = _mm_mullo_epi16(brAG, dxdy); \ |
| brAG = _mm_mullo_epi16(brAG, dxdy); \ |
| brRB = _mm_mullo_epi16(brRB, dxdy); \ |
| brRB = _mm_mullo_epi16(brRB, dxdy); \ |
| \ |
| \ |
| /* Add the values, and shift to only keep 8 significant bits per colors */ \ |
| /* Add the values, and shift to only keep 8 significant bits per colors */ \ |
| __m128i rAG =_mm_add_epi16(_mm_add_epi16(tlAG, trAG), _mm_add_epi16(blAG, brAG)); \ |
| __m128i rAG =_mm_add_epi16(_mm_add_epi16(tlAG, trAG), _mm_add_epi16(blAG, brAG)); \ |
| __m128i rRB =_mm_add_epi16(_mm_add_epi16(tlRB, trRB), _mm_add_epi16(blRB, brRB)); \ |
| __m128i rRB =_mm_add_epi16(_mm_add_epi16(tlRB, trRB), _mm_add_epi16(blRB, brRB)); \ |
| rAG = _mm_andnot_si128(colorMask, rAG); \ |
| rAG = _mm_andnot_si128(colorMask, rAG); \ |
| rRB = _mm_srli_epi16(rRB, 8); \ |
| rRB = _mm_srli_epi16(rRB, 8); \ |
| _mm_storeu_si128((__m128i*)(b), _mm_or_si128(rAG, rRB)); \ |
| _mm_storeu_si128((__m128i*)(b), _mm_or_si128(rAG, rRB)); \ |
| } |
| } |
| #endif |
| #endif |
| |
| |
| |
| #if defined(QT_ALWAYS_HAVE_NEON) |
| |
| #define interpolate_4_pixels_16_neon(tl, tr, bl, br, distx, disty, disty_, colorMask, invColorMask, v_256, b) \ |
| |
| { \ |
| |
| const int16x8_t dxdy = vmulq_s16(distx, disty); \ |
| |
| const int16x8_t distx_ = vshlq_n_s16(distx, 4); \ |
| |
| const int16x8_t idxidy = vaddq_s16(dxdy, vsubq_s16(v_256, vaddq_s16(distx_, disty_))); \ |
| |
| const int16x8_t dxidy = vsubq_s16(distx_, dxdy); \ |
| |
| const int16x8_t idxdy = vsubq_s16(disty_, dxdy); \ |
| |
| \ |
| |
| int16x8_t tlAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(tl), 8)); \ |
| |
| int16x8_t tlRB = vandq_s16(tl, colorMask); \ |
| |
| int16x8_t trAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(tr), 8)); \ |
| |
| int16x8_t trRB = vandq_s16(tr, colorMask); \ |
| |
| int16x8_t blAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(bl), 8)); \ |
| |
| int16x8_t blRB = vandq_s16(bl, colorMask); \ |
| |
| int16x8_t brAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(br), 8)); \ |
| |
| int16x8_t brRB = vandq_s16(br, colorMask); \ |
| |
| \ |
| |
| int16x8_t rAG = vmulq_s16(tlAG, idxidy); \ |
| |
| int16x8_t rRB = vmulq_s16(tlRB, idxidy); \ |
| |
| rAG = vmlaq_s16(rAG, trAG, dxidy); \ |
| |
| rRB = vmlaq_s16(rRB, trRB, dxidy); \ |
| |
| rAG = vmlaq_s16(rAG, blAG, idxdy); \ |
| |
| rRB = vmlaq_s16(rRB, blRB, idxdy); \ |
| |
| rAG = vmlaq_s16(rAG, brAG, dxdy); \ |
| |
| rRB = vmlaq_s16(rRB, brRB, dxdy); \ |
| |
| \ |
| |
| rAG = vandq_s16(invColorMask, rAG); \ |
| |
| rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8)); \ |
| |
| vst1q_s16((int16_t*)(b), vorrq_s16(rAG, rRB)); \ |
| |
| } |
| |
| #endif |
| |
| |
| template<TextureBlendType blendType> |
| template<TextureBlendType blendType> |
| Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) |
| Q_STATIC_TEMPLATE_FUNCTION inline void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2) |
| { |
| { |
| if (blendType == BlendTransformedBilinearTiled) { |
| if (blendType == BlendTransformedBilinearTiled) { |
| v1 %= max; |
| v1 %= max; |
| if (v1 < 0) v1 += max; |
| if (v1 < 0) v1 += max; |
| v2 = v1 + 1; |
| v2 = v1 + 1; |
| v2 %= max; |
| v2 %= max; |
| } else { |
| } else { |
| if (v1 < l1) { |
| if (v1 < l1) { |
| v2 = v1 = l1; |
| v2 = v1 = l1; |
| } else if (v1 >= l2) { |
| } else if (v1 >= l2) { |
| v2 = v1 = l2; |
| v2 = v1 = l2; |
| } else { |
| } else { |
| v2 = v1 + 1; |
| v2 = v1 + 1; |
| } |
| } |
| } |
| } |
| |
| |
| Q_ASSERT(v1 >= 0 && v1 < max); |
| Q_ASSERT(v1 >= 0 && v1 < max); |
| Q_ASSERT(v2 >= 0 && v2 < max); |
| Q_ASSERT(v2 >= 0 && v2 < max); |
| } |
| } |
| |
| |
| template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ |
| template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */ |
| Q_STATIC_TEMPLATE_FUNCTION |
| Q_STATIC_TEMPLATE_FUNCTION |
| const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, |
| const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| #ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 |
| #ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 |
| FetchPixelProc fetch; |
| FetchPixelProc fetch; |
| if (format != QImage::Format_Invalid) |
| if (format != QImage::Format_Invalid) |
| fetch = qt_fetchPixel<format>; |
| fetch = qt_fetchPixel<format>; |
| else |
| else |
| fetch = fetchPixelProc[data->texture.format]; |
| fetch = fetchPixelProc[data->texture.format]; |
| #else |
| #else |
| FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; |
| FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format]; |
| #endif |
| #endif |
| |
| |
| int image_width = data->texture.width; |
| int image_width = data->texture.width; |
| int image_height = data->texture.height; |
| int image_height = data->texture.height; |
| |
| |
| int image_x1 = data->texture.x1; |
| int image_x1 = data->texture.x1; |
| int image_y1 = data->texture.y1; |
| int image_y1 = data->texture.y1; |
| int image_x2 = data->texture.x2 - 1; |
| int image_x2 = data->texture.x2 - 1; |
| int image_y2 = data->texture.y2 - 1; |
| int image_y2 = data->texture.y2 - 1; |
| |
| |
| const qreal cx = x + 0.5; |
| const qreal cx = x + 0.5; |
| const qreal cy = y + 0.5; |
| const qreal cy = y + 0.5; |
| |
| |
| uint *end = buffer + length; |
| uint *end = buffer + length; |
| uint *b = buffer; |
| uint *b = buffer; |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| int fx = int((data->m21 * cy |
| int fx = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int fy = int((data->m22 * cy |
| int fy = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| |
| |
| fx -= half_point; |
| fx -= half_point; |
| fy -= half_point; |
| fy -= half_point; |
| |
| |
| if (fdy == 0) { //simple scale, no rotation |
| if (fdy == 0) { //simple scale, no rotation |
| int y1 = (fy >> 16); |
| int y1 = (fy >> 16); |
| int y2; |
| int y2; |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| |
| |
| if (fdx <= fixed_scale && fdx > 0) { // scale up on X |
| if (fdx <= fixed_scale && fdx > 0) { // scale up on X |
| int disty = (fy & 0x0000ffff) >> 8; |
| int disty = (fy & 0x0000ffff) >> 8; |
| int idisty = 256 - disty; |
| int idisty = 256 - disty; |
| int x = fx >> 16; |
| int x = fx >> 16; |
| |
| |
| // The idea is first to do the interpolation between the row s1 and the row s2 |
| // 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. |
| // into an intermediate buffer, then we interpolate between two pixel of this buffer. |
| |
| |
| // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB |
| // intermediate_buffer[0] is a buffer of red-blue component of the pixel, in the form 0x00RR00BB |
| // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG |
| // intermediate_buffer[1] is the alpha-green component of the pixel, in the form 0x00AA00GG |
| quint32 intermediate_buffer[2][buffer_size + 2]; |
| quint32 intermediate_buffer[2][buffer_size + 2]; |
| // count is the size used in the intermediate_buffer. |
| // count is the size used in the intermediate_buffer. |
| int count = qCeil(length * data->m11) + 2; //+1 for the last pixel to interpolate with, and +1 for rounding errors. |
| 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 |
| Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case |
| int f = 0; |
| int f = 0; |
| int lim = count; |
| int lim = count; |
| if (blendType == BlendTransformedBilinearTiled) { |
| if (blendType == BlendTransformedBilinearTiled) { |
| x %= image_width; |
| x %= image_width; |
| if (x < 0) x += image_width; |
| if (x < 0) x += image_width; |
| } else { |
| } else { |
| lim = qMin(count, image_x2-x+1); |
| lim = qMin(count, image_x2-x+1); |
| if (x < image_x1) { |
| if (x < image_x1) { |
| Q_ASSERT(x <= image_x2); |
| Q_ASSERT(x <= image_x2); |
| uint t = fetch(s1, image_x1, data->texture.colorTable); |
| uint t = fetch(s1, image_x1, data->texture.colorTable); |
| uint b = fetch(s2, image_x1, data->texture.colorTable); |
| uint b = fetch(s2, image_x1, data->texture.colorTable); |
| quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| quint32 rb = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| quint32 ag = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| do { |
| do { |
| intermediate_buffer[0][f] = rb; |
| intermediate_buffer[0][f] = rb; |
| intermediate_buffer[1][f] = ag; |
| intermediate_buffer[1][f] = ag; |
| f++; |
| f++; |
| x++; |
| x++; |
| } while (x < image_x1 && f < lim); |
| } while (x < image_x1 && f < lim); |
| } |
| } |
| } |
| } |
| |
| |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| |
| if (blendType != BlendTransformedBilinearTiled && |
| if (blendType != BlendTransformedBilinearTiled && |
| (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { |
| (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { |
| |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| const __m128i disty_ = _mm_set1_epi16(disty); |
| const __m128i disty_ = _mm_set1_epi16(disty); |
| const __m128i idisty_ = _mm_set1_epi16(idisty); |
| const __m128i idisty_ = _mm_set1_epi16(idisty); |
| const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); |
| const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); |
| |
| |
| lim -= 3; |
| lim -= 3; |
| for (; f < lim; x += 4, f += 4) { |
| for (; f < lim; x += 4, f += 4) { |
| // Load 4 pixels from s1, and split the alpha-green and red-blue component |
| // Load 4 pixels from s1, and split the alpha-green and red-blue component |
| __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x)); |
| __m128i top = _mm_loadu_si128((__m128i*)((const uint *)(s1)+x)); |
| __m128i topAG = _mm_srli_epi16(top, 8); |
| __m128i topAG = _mm_srli_epi16(top, 8); |
| __m128i topRB = _mm_and_si128(top, colorMask); |
| __m128i topRB = _mm_and_si128(top, colorMask); |
| // Multiplies each colour component by idisty |
| // Multiplies each colour component by idisty |
| topAG = _mm_mullo_epi16 (topAG, idisty_); |
| topAG = _mm_mullo_epi16 (topAG, idisty_); |
| topRB = _mm_mullo_epi16 (topRB, idisty_); |
| topRB = _mm_mullo_epi16 (topRB, idisty_); |
| |
| |
| // Same for the s2 vector |
| // Same for the s2 vector |
| __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x)); |
| __m128i bottom = _mm_loadu_si128((__m128i*)((const uint *)(s2)+x)); |
| __m128i bottomAG = _mm_srli_epi16(bottom, 8); |
| __m128i bottomAG = _mm_srli_epi16(bottom, 8); |
| __m128i bottomRB = _mm_and_si128(bottom, colorMask); |
| __m128i bottomRB = _mm_and_si128(bottom, colorMask); |
| bottomAG = _mm_mullo_epi16 (bottomAG, disty_); |
| bottomAG = _mm_mullo_epi16 (bottomAG, disty_); |
| bottomRB = _mm_mullo_epi16 (bottomRB, disty_); |
| bottomRB = _mm_mullo_epi16 (bottomRB, disty_); |
| |
| |
| // Add the values, and shift to only keep 8 significant bits per colors |
| // Add the values, and shift to only keep 8 significant bits per colors |
| __m128i rAG =_mm_add_epi16(topAG, bottomAG); |
| __m128i rAG =_mm_add_epi16(topAG, bottomAG); |
| rAG = _mm_srli_epi16(rAG, 8); |
| rAG = _mm_srli_epi16(rAG, 8); |
| _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); |
| _mm_storeu_si128((__m128i*)(&intermediate_buffer[1][f]), rAG); |
| __m128i rRB =_mm_add_epi16(topRB, bottomRB); |
| __m128i rRB =_mm_add_epi16(topRB, bottomRB); |
| rRB = _mm_srli_epi16(rRB, 8); |
| rRB = _mm_srli_epi16(rRB, 8); |
| _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); |
| _mm_storeu_si128((__m128i*)(&intermediate_buffer[0][f]), rRB); |
| } |
| } |
| } |
| #elif defined(QT_ALWAYS_HAVE_NEON) |
| |
| const int16x8_t disty_ = vdupq_n_s16(disty); |
| |
| const int16x8_t idisty_ = vdupq_n_s16(idisty); |
| |
| const int16x8_t colorMask = vdupq_n_s16(0x00ff); |
| |
| |
| |
| lim -= 3; |
| |
| for (; f < lim; x += 4, f += 4) { |
| |
| // Load 4 pixels from s1, and split the alpha-green and red-blue component |
| |
| int16x8_t top = vld1q_s16((int16_t*)((const uint *)(s1)+x)); |
| |
| int16x8_t topAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(top), 8)); |
| |
| int16x8_t topRB = vandq_s16(top, colorMask); |
| |
| // Multiplies each colour component by idisty |
| |
| topAG = vmulq_s16(topAG, idisty_); |
| |
| topRB = vmulq_s16(topRB, idisty_); |
| |
| |
| |
| // Same for the s2 vector |
| |
| int16x8_t bottom = vld1q_s16((int16_t*)((const uint *)(s2)+x)); |
| |
| int16x8_t bottomAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(bottom), 8)); |
| |
| int16x8_t bottomRB = vandq_s16(bottom, colorMask); |
| |
| bottomAG = vmulq_s16(bottomAG, disty_); |
| |
| bottomRB = vmulq_s16(bottomRB, disty_); |
| |
| |
| |
| // Add the values, and shift to only keep 8 significant bits per colors |
| |
| int16x8_t rAG = vaddq_s16(topAG, bottomAG); |
| |
| rAG = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rAG), 8)); |
| |
| vst1q_s16((int16_t*)(&intermediate_buffer[1][f]), rAG); |
| |
| int16x8_t rRB = vaddq_s16(topRB, bottomRB); |
| |
| rRB = vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(rRB), 8)); |
| |
| vst1q_s16((int16_t*)(&intermediate_buffer[0][f]), rRB); |
| |
| } |
| #endif |
| #endif |
| |
| } |
| for (; f < count; f++) { // Same as above but without sse2 |
| for (; f < count; f++) { // Same as above but without sse2 |
| if (blendType == BlendTransformedBilinearTiled) { |
| if (blendType == BlendTransformedBilinearTiled) { |
| if (x >= image_width) x -= image_width; |
| if (x >= image_width) x -= image_width; |
| } else { |
| } else { |
| x = qMin(x, image_x2); |
| x = qMin(x, image_x2); |
| } |
| } |
| |
| |
| uint t = fetch(s1, x, data->texture.colorTable); |
| uint t = fetch(s1, x, data->texture.colorTable); |
| uint b = fetch(s2, x, data->texture.colorTable); |
| uint b = fetch(s2, x, data->texture.colorTable); |
| |
| |
| intermediate_buffer[0][f] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| 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; |
| intermediate_buffer[1][f] = ((((t>>8) & 0xff00ff) * idisty + ((b>>8) & 0xff00ff) * disty) >> 8) & 0xff00ff; |
| x++; |
| x++; |
| } |
| } |
| // Now interpolate the values from the intermediate_buffer to get the final result. |
| // Now interpolate the values from the intermediate_buffer to get the final result. |
| fx &= fixed_scale - 1; |
| fx &= fixed_scale - 1; |
| Q_ASSERT((fx >> 16) == 0); |
| Q_ASSERT((fx >> 16) == 0); |
| while (b < end) { |
| while (b < end) { |
| register int x1 = (fx >> 16); |
| register int x1 = (fx >> 16); |
| register int x2 = x1 + 1; |
| register int x2 = x1 + 1; |
| Q_ASSERT(x1 >= 0); |
| Q_ASSERT(x1 >= 0); |
| Q_ASSERT(x2 < count); |
| Q_ASSERT(x2 < count); |
| |
| |
| register int distx = (fx & 0x0000ffff) >> 8; |
| register int distx = (fx & 0x0000ffff) >> 8; |
| register int idistx = 256 - distx; |
| register int idistx = 256 - distx; |
| int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; |
| int rb = ((intermediate_buffer[0][x1] * idistx + intermediate_buffer[0][x2] * distx) >> 8) & 0xff00ff; |
| int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; |
| int ag = (intermediate_buffer[1][x1] * idistx + intermediate_buffer[1][x2] * distx) & 0xff00ff00; |
| *b = rb | ag; |
| *b = rb | ag; |
| b++; |
| b++; |
| fx += fdx; |
| fx += fdx; |
| } |
| } |
| } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x |
| } else if ((fdx < 0 && fdx > -(fixed_scale / 8)) || fabs(data->m22) < (1./8.)) { // scale up more than 8x |
| int y1 = (fy >> 16); |
| int y1 = (fy >> 16); |
| int y2; |
| int y2; |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| int disty = (fy & 0x0000ffff) >> 8; |
| int disty = (fy & 0x0000ffff) >> 8; |
| int idisty = 256 - disty; |
| int idisty = 256 - disty; |
| while (b < end) { |
| while (b < end) { |
| int x1 = (fx >> 16); |
| int x1 = (fx >> 16); |
| int x2; |
| int x2; |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| |
| |
| int distx = (fx & 0x0000ffff) >> 8; |
| int distx = (fx & 0x0000ffff) >> 8; |
| int idistx = 256 - distx; |
| int idistx = 256 - distx; |
| |
| |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| |
| |
| fx += fdx; |
| fx += fdx; |
| ++b; |
| ++b; |
| } |
| } |
| } else { //scale down |
| } else { //scale down |
| int y1 = (fy >> 16); |
| int y1 = (fy >> 16); |
| int y2; |
| int y2; |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| int disty = (fy & 0x0000ffff) >> 12; |
| int disty = (fy & 0x0000ffff) >> 12; |
| |
| |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| |
| if (blendType != BlendTransformedBilinearTiled && |
| if (blendType != BlendTransformedBilinearTiled && |
| (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { |
| (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)) { |
| |
| |
| //prolog to get into the bounds |
| #define BILINEAR_DOWNSCALE_BOUNDS_PROLOG \ |
| while (b < end) { |
| while (b < end) { \ |
| int x1 = (fx >> 16); |
| int x1 = (fx >> 16); \ |
| int x2; |
| int x2; \ |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); \ |
| if (x1 != x2) //break if we are insided the bounds. |
| if (x1 != x2) \ |
| break; |
| break; \ |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); \ |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); \ |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); \ |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); \ |
| int distx = (fx & 0x0000ffff) >> 12; |
| int distx = (fx & 0x0000ffff) >> 12; \ |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); \ |
| fx += fdx; |
| fx += fdx; \ |
| ++b; |
| ++b; \ |
| } |
| } \ |
| uint *boundedEnd; |
| uint *boundedEnd; \ |
| if (fdx > 0) |
| if (fdx > 0) \ |
| boundedEnd = qMin(end, buffer + uint((image_x2 - (fx >> 16)) / data->m11)); |
| boundedEnd = qMin(end, buffer + uint((image_x2 - (fx >> 16)) / data->m11)); \ |
| else |
| else \ |
| boundedEnd = qMin(end, buffer + uint((image_x1 - (fx >> 16)) / data->m11)); |
| boundedEnd = qMin(end, buffer + uint((image_x1 - (fx >> 16)) / data->m11)); \ |
| boundedEnd -= 3; |
| boundedEnd -= 3; |
| |
| |
| |
| #if defined(QT_ALWAYS_HAVE_SSE2) |
| |
| BILINEAR_DOWNSCALE_BOUNDS_PROLOG |
| |
| |
| const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); |
| const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); |
| //const __m128i distShuffleMask = _mm_set_epi8(13, 12, 13, 12, 9, 8, 9, 8, 5, 4, 5, 4, 1, 0, 1, 0); |
| |
| const __m128i v_256 = _mm_set1_epi16(256); |
| const __m128i v_256 = _mm_set1_epi16(256); |
| const __m128i v_disty = _mm_set1_epi16(disty); |
| const __m128i v_disty = _mm_set1_epi16(disty); |
| __m128i v_fdx = _mm_set1_epi32(fdx*4); |
| __m128i v_fdx = _mm_set1_epi32(fdx*4); |
| |
| |
| ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1); |
| ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1); |
| |
| |
| union Vect_buffer { __m128i vect; quint32 i[4]; }; |
| union Vect_buffer { __m128i vect; quint32 i[4]; }; |
| Vect_buffer v_fx; |
| Vect_buffer v_fx; |
| |
| |
| for (int i = 0; i < 4; i++) { |
| for (int i = 0; i < 4; i++) { |
| v_fx.i[i] = fx; |
| v_fx.i[i] = fx; |
| fx += fdx; |
| fx += fdx; |
| } |
| } |
| |
| |
| while (b < boundedEnd) { |
| while (b < boundedEnd) { |
| |
| |
| Vect_buffer tl, tr, bl, br; |
| Vect_buffer tl, tr, bl, br; |
| |
| |
| for (int i = 0; i < 4; i++) { |
| for (int i = 0; i < 4; i++) { |
| int x1 = v_fx.i[i] >> 16; |
| int x1 = v_fx.i[i] >> 16; |
| const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1; |
| const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1; |
| const uint *addr_tr = addr_tl + 1; |
| const uint *addr_tr = addr_tl + 1; |
| tl.i[i] = *addr_tl; |
| tl.i[i] = *addr_tl; |
| tr.i[i] = *addr_tr; |
| tr.i[i] = *addr_tr; |
| bl.i[i] = *(addr_tl+secondLine); |
| bl.i[i] = *(addr_tl+secondLine); |
| br.i[i] = *(addr_tr+secondLine); |
| br.i[i] = *(addr_tr+secondLine); |
| } |
| } |
| __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12); //distx = (fx & 0x0000ffff) >> 12; |
| __m128i v_distx = _mm_srli_epi16(v_fx.vect, 12); |
| //v_distx = _mm_shuffle_epi8(v_disty, distShuffleMask); //distx |= distx << 16; |
| |
| v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); |
| v_distx = _mm_shufflehi_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); |
| v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); |
| v_distx = _mm_shufflelo_epi16(v_distx, _MM_SHUFFLE(2,2,0,0)); |
| |
| |
| interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b); |
| interpolate_4_pixels_16_sse2(tl.vect, tr.vect, bl.vect, br.vect, v_distx, v_disty, colorMask, v_256, b); |
| b+=4; |
| b+=4; |
| v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx); |
| v_fx.vect = _mm_add_epi32(v_fx.vect, v_fdx); |
| } |
| } |
| fx = v_fx.i[0]; |
| fx = v_fx.i[0]; |
| } |
| #elif defined(QT_ALWAYS_HAVE_NEON) |
| |
| BILINEAR_DOWNSCALE_BOUNDS_PROLOG |
| |
| |
| |
| const int16x8_t colorMask = vdupq_n_s16(0x00ff); |
| |
| const int16x8_t invColorMask = vmvnq_s16(colorMask); |
| |
| const int16x8_t v_256 = vdupq_n_s16(256); |
| |
| const int16x8_t v_disty = vdupq_n_s16(disty); |
| |
| const int16x8_t v_disty_ = vshlq_n_s16(v_disty, 4); |
| |
| int32x4_t v_fdx = vdupq_n_s32(fdx*4); |
| |
| |
| |
| ptrdiff_t secondLine = reinterpret_cast<const uint *>(s2) - reinterpret_cast<const uint *>(s1); |
| |
| |
| |
| union Vect_buffer { int32x4_t vect; quint32 i[4]; }; |
| |
| Vect_buffer v_fx; |
| |
| |
| |
| for (int i = 0; i < 4; i++) { |
| |
| v_fx.i[i] = fx; |
| |
| fx += fdx; |
| |
| } |
| |
| |
| |
| const int32x4_t v_ffff_mask = vdupq_n_s32(0x0000ffff); |
| |
| |
| |
| while (b < boundedEnd) { |
| |
| |
| |
| Vect_buffer tl, tr, bl, br; |
| |
| |
| |
| Vect_buffer v_fx_shifted; |
| |
| v_fx_shifted.vect = vshrq_n_s32(v_fx.vect, 16); |
| |
| |
| |
| int32x4_t v_distx = vshrq_n_s32(vandq_s32(v_fx.vect, v_ffff_mask), 12); |
| |
| |
| |
| for (int i = 0; i < 4; i++) { |
| |
| int x1 = v_fx_shifted.i[i]; |
| |
| const uint *addr_tl = reinterpret_cast<const uint *>(s1) + x1; |
| |
| const uint *addr_tr = addr_tl + 1; |
| |
| tl.i[i] = *addr_tl; |
| |
| tr.i[i] = *addr_tr; |
| |
| bl.i[i] = *(addr_tl+secondLine); |
| |
| br.i[i] = *(addr_tr+secondLine); |
| |
| } |
| |
| |
| |
| v_distx = vorrq_s32(v_distx, vshlq_n_s32(v_distx, 16)); |
| |
| |
| |
| interpolate_4_pixels_16_neon(vreinterpretq_s16_s32(tl.vect), vreinterpretq_s16_s32(tr.vect), vreinterpretq_s16_s32(bl.vect), vreinterpretq_s16_s32(br.vect), vreinterpretq_s16_s32(v_distx), v_disty, v_disty_, colorMask, invColorMask, v_256, b); |
| |
| b+=4; |
| |
| v_fx.vect = vaddq_s32(v_fx.vect, v_fdx); |
| |
| } |
| |
| fx = v_fx.i[0]; |
| #endif |
| #endif |
| |
| } |
| |
| |
| while (b < end) { |
| while (b < end) { |
| int x1 = (fx >> 16); |
| int x1 = (fx >> 16); |
| int x2; |
| int x2; |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| int distx = (fx & 0x0000ffff) >> 12; |
| int distx = (fx & 0x0000ffff) >> 12; |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); |
| fx += fdx; |
| fx += fdx; |
| ++b; |
| ++b; |
| } |
| } |
| } |
| } |
| } else { //rotation |
| } else { //rotation |
| if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { |
| if (fabs(data->m11) > 8 || fabs(data->m22) > 8) { |
| //if we are zooming more than 8 times, we use 8bit precision for the position. |
| //if we are zooming more than 8 times, we use 8bit precision for the position. |
| while (b < end) { |
| while (b < end) { |
| int x1 = (fx >> 16); |
| int x1 = (fx >> 16); |
| int x2; |
| int x2; |
| int y1 = (fy >> 16); |
| int y1 = (fy >> 16); |
| int y2; |
| int y2; |
| |
| |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| |
| |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| |
| |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| |
| |
| int distx = (fx & 0x0000ffff) >> 8; |
| int distx = (fx & 0x0000ffff) >> 8; |
| int disty = (fy & 0x0000ffff) >> 8; |
| int disty = (fy & 0x0000ffff) >> 8; |
| int idistx = 256 - distx; |
| int idistx = 256 - distx; |
| int idisty = 256 - disty; |
| int idisty = 256 - disty; |
| |
| |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| |
| |
| fx += fdx; |
| fx += fdx; |
| fy += fdy; |
| fy += fdy; |
| ++b; |
| ++b; |
| } |
| } |
| } else { |
| } else { |
| //we are zooming less than 8x, use 4bit precision |
| //we are zooming less than 8x, use 4bit precision |
| while (b < end) { |
| while (b < end) { |
| int x1 = (fx >> 16); |
| int x1 = (fx >> 16); |
| int x2; |
| int x2; |
| int y1 = (fy >> 16); |
| int y1 = (fy >> 16); |
| int y2; |
| int y2; |
| |
| |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| |
| |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| |
| |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| |
| |
| int distx = (fx & 0x0000ffff) >> 12; |
| int distx = (fx & 0x0000ffff) >> 12; |
| int disty = (fy & 0x0000ffff) >> 12; |
| int disty = (fy & 0x0000ffff) >> 12; |
| |
| |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); |
| *b = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty); |
| |
| |
| fx += fdx; |
| fx += fdx; |
| fy += fdy; |
| fy += fdy; |
| ++b; |
| ++b; |
| } |
| } |
| } |
| } |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| |
| |
| qreal fx = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal fx = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal fy = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal fy = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal fw = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal fw = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = fw == 0 ? 1 : 1 / fw; |
| const qreal iw = fw == 0 ? 1 : 1 / fw; |
| const qreal px = fx * iw - 0.5; |
| const qreal px = fx * iw - 0.5; |
| const qreal py = fy * iw - 0.5; |
| const qreal py = fy * iw - 0.5; |
| |
| |
| int x1 = int(px) - (px < 0); |
| int x1 = int(px) - (px < 0); |
| int x2; |
| int x2; |
| int y1 = int(py) - (py < 0); |
| int y1 = int(py) - (py < 0); |
| int y2; |
| int y2; |
| |
| |
| int distx = int((px - x1) * 256); |
| int distx = int((px - x1) * 256); |
| int disty = int((py - y1) * 256); |
| int disty = int((py - y1) * 256); |
| int idistx = 256 - distx; |
| int idistx = 256 - distx; |
| int idisty = 256 - disty; |
| int idisty = 256 - disty; |
| |
| |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2); |
| |
| |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s1 = data->texture.scanLine(y1); |
| const uchar *s2 = data->texture.scanLine(y2); |
| const uchar *s2 = data->texture.scanLine(y2); |
| |
| |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tl = fetch(s1, x1, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint tr = fetch(s1, x2, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint bl = fetch(s2, x1, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| uint br = fetch(s2, x2, data->texture.colorTable); |
| |
| |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); |
| |
| |
| fx += fdx; |
| fx += fdx; |
| fy += fdy; |
| fy += fdy; |
| fw += fdw; |
| fw += fdw; |
| //force increment to avoid /0 |
| //force increment to avoid /0 |
| if (!fw) { |
| if (!fw) { |
| fw += fdw; |
| fw += fdw; |
| } |
| } |
| ++b; |
| ++b; |
| } |
| } |
| } |
| } |
| |
| |
| return buffer; |
| return buffer; |
| } |
| } |
| |
| |
| #define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg> |
| #define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg> |
| |
| |
| static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { |
| static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { |
| // Untransformed |
| // Untransformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied |
| }, |
| }, |
| // Tiled |
| // Tiled |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Mono), // Mono |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_MonoLSB), // MonoLsb |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_Indexed8), // Indexed8 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // RGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32), // ARGB32 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB32_Premultiplied), // ARGB32_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB16), // RGB16 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8565_Premultiplied),// ARGB8565_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB666), // RGB666 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB6666_Premultiplied),// ARGB6666_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB555), // RGB555 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB8555_Premultiplied),// ARGB8555_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB888), // RGB888 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_RGB444), // RGB444 |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied |
| SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Format_ARGB4444_Premultiplied) // ARGB4444_Premultiplied |
| }, |
| }, |
| // Transformed |
| // Transformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| fetchTransformed<BlendTransformed>, // Mono |
| fetchTransformed<BlendTransformed>, // Mono |
| fetchTransformed<BlendTransformed>, // MonoLsb |
| fetchTransformed<BlendTransformed>, // MonoLsb |
| fetchTransformed<BlendTransformed>, // Indexed8 |
| fetchTransformed<BlendTransformed>, // Indexed8 |
| fetchTransformed<BlendTransformed>, // RGB32 |
| fetchTransformed<BlendTransformed>, // RGB32 |
| fetchTransformed<BlendTransformed>, // ARGB32 |
| fetchTransformed<BlendTransformed>, // ARGB32 |
| fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied |
| fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied |
| fetchTransformed<BlendTransformed>, // RGB16 |
| fetchTransformed<BlendTransformed>, // RGB16 |
| fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied |
| fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied |
| fetchTransformed<BlendTransformed>, // RGB666 |
| fetchTransformed<BlendTransformed>, // RGB666 |
| fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied |
| fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied |
| fetchTransformed<BlendTransformed>, // RGB555 |
| fetchTransformed<BlendTransformed>, // RGB555 |
| fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied |
| fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied |
| fetchTransformed<BlendTransformed>, // RGB888 |
| fetchTransformed<BlendTransformed>, // RGB888 |
| fetchTransformed<BlendTransformed>, // RGB444 |
| fetchTransformed<BlendTransformed>, // RGB444 |
| fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied |
| fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied |
| }, |
| }, |
| { |
| { |
| 0, // TransformedTiled |
| 0, // TransformedTiled |
| fetchTransformed<BlendTransformedTiled>, // Mono |
| fetchTransformed<BlendTransformedTiled>, // Mono |
| fetchTransformed<BlendTransformedTiled>, // MonoLsb |
| fetchTransformed<BlendTransformedTiled>, // MonoLsb |
| fetchTransformed<BlendTransformedTiled>, // Indexed8 |
| fetchTransformed<BlendTransformedTiled>, // Indexed8 |
| fetchTransformed<BlendTransformedTiled>, // RGB32 |
| fetchTransformed<BlendTransformedTiled>, // RGB32 |
| fetchTransformed<BlendTransformedTiled>, // ARGB32 |
| fetchTransformed<BlendTransformedTiled>, // ARGB32 |
| fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // RGB16 |
| fetchTransformed<BlendTransformedTiled>, // RGB16 |
| fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // RGB666 |
| fetchTransformed<BlendTransformedTiled>, // RGB666 |
| fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // RGB555 |
| fetchTransformed<BlendTransformedTiled>, // RGB555 |
| fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // RGB888 |
| fetchTransformed<BlendTransformedTiled>, // RGB888 |
| fetchTransformed<BlendTransformedTiled>, // RGB444 |
| fetchTransformed<BlendTransformedTiled>, // RGB444 |
| fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied |
| fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied |
| }, |
| }, |
| { |
| { |
| 0, // Bilinear |
| 0, // Bilinear |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444 |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied |
| }, |
| }, |
| { |
| { |
| 0, // BilinearTiled |
| 0, // BilinearTiled |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444 |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied |
| fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied |
| }, |
| }, |
| }; |
| }; |
| |
| |
| |
| |
| static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) |
| static inline uint qt_gradient_pixel(const QGradientData *data, qreal pos) |
| { |
| { |
| int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + 0.5); |
| int ipos = int(pos * (GRADIENT_STOPTABLE_SIZE - 1) + 0.5); |
| |
| |
| // calculate the actual offset. |
| // calculate the actual offset. |
| if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) { |
| if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) { |
| if (data->spread == QGradient::RepeatSpread) { |
| if (data->spread == QGradient::RepeatSpread) { |
| ipos = ipos % GRADIENT_STOPTABLE_SIZE; |
| ipos = ipos % GRADIENT_STOPTABLE_SIZE; |
| ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos; |
| ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos; |
| |
| |
| } else if (data->spread == QGradient::ReflectSpread) { |
| } else if (data->spread == QGradient::ReflectSpread) { |
| const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1; |
| const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1; |
| ipos = ipos % limit; |
| ipos = ipos % limit; |
| ipos = ipos < 0 ? limit + ipos : ipos; |
| ipos = ipos < 0 ? limit + ipos : ipos; |
| ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; |
| ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; |
| |
| |
| } else { |
| } else { |
| if (ipos < 0) ipos = 0; |
| if (ipos < 0) ipos = 0; |
| else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1; |
| else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1; |
| } |
| } |
| } |
| } |
| |
| |
| Q_ASSERT(ipos >= 0); |
| Q_ASSERT(ipos >= 0); |
| Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE); |
| Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE); |
| |
| |
| return data->colorTable[ipos]; |
| return data->colorTable[ipos]; |
| } |
| } |
| |
| |
| #define FIXPT_BITS 8 |
| #define FIXPT_BITS 8 |
| #define FIXPT_SIZE (1<<FIXPT_BITS) |
| #define FIXPT_SIZE (1<<FIXPT_BITS) |
| |
| |
| static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) |
| static uint qt_gradient_pixel_fixed(const QGradientData *data, int fixed_pos) |
| { |
| { |
| int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; |
| int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; |
| |
| |
| // calculate the actual offset. |
| // calculate the actual offset. |
| if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) { |
| if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) { |
| if (data->spread == QGradient::RepeatSpread) { |
| if (data->spread == QGradient::RepeatSpread) { |
| ipos = ipos % GRADIENT_STOPTABLE_SIZE; |
| ipos = ipos % GRADIENT_STOPTABLE_SIZE; |
| ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos; |
| ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos; |
| |
| |
| } else if (data->spread == QGradient::ReflectSpread) { |
| } else if (data->spread == QGradient::ReflectSpread) { |
| const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1; |
| const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1; |
| ipos = ipos % limit; |
| ipos = ipos % limit; |
| ipos = ipos < 0 ? limit + ipos : ipos; |
| ipos = ipos < 0 ? limit + ipos : ipos; |
| ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; |
| ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; |
| |
| |
| } else { |
| } else { |
| if (ipos < 0) ipos = 0; |
| if (ipos < 0) ipos = 0; |
| else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1; |
| else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1; |
| } |
| } |
| } |
| } |
| |
| |
| Q_ASSERT(ipos >= 0); |
| Q_ASSERT(ipos >= 0); |
| Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE); |
| Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE); |
| |
| |
| return data->colorTable[ipos]; |
| return data->colorTable[ipos]; |
| } |
| } |
| |
| |
| static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data) |
| static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data) |
| { |
| { |
| v->dx = data->gradient.linear.end.x - data->gradient.linear.origin.x; |
| v->dx = data->gradient.linear.end.x - data->gradient.linear.origin.x; |
| v->dy = data->gradient.linear.end.y - data->gradient.linear.origin.y; |
| v->dy = data->gradient.linear.end.y - data->gradient.linear.origin.y; |
| v->l = v->dx * v->dx + v->dy * v->dy; |
| v->l = v->dx * v->dx + v->dy * v->dy; |
| v->off = 0; |
| v->off = 0; |
| if (v->l != 0) { |
| if (v->l != 0) { |
| v->dx /= v->l; |
| v->dx /= v->l; |
| v->dy /= v->l; |
| v->dy /= v->l; |
| v->off = -v->dx * data->gradient.linear.origin.x - v->dy * data->gradient.linear.origin.y; |
| v->off = -v->dx * data->gradient.linear.origin.x - v->dy * data->gradient.linear.origin.y; |
| } |
| } |
| } |
| } |
| |
| |
| static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator *op, const QSpanData *data, |
| static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator *op, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| const uint *b = buffer; |
| const uint *b = buffer; |
| qreal t, inc; |
| qreal t, inc; |
| |
| |
| bool affine = true; |
| bool affine = true; |
| qreal rx=0, ry=0; |
| qreal rx=0, ry=0; |
| if (op->linear.l == 0) { |
| if (op->linear.l == 0) { |
| t = inc = 0; |
| t = inc = 0; |
| } else { |
| } else { |
| rx = data->m21 * (y + 0.5) + data->m11 * (x + 0.5) + data->dx; |
| rx = data->m21 * (y + 0.5) + data->m11 * (x + 0.5) + data->dx; |
| ry = data->m22 * (y + 0.5) + data->m12 * (x + 0.5) + data->dy; |
| ry = data->m22 * (y + 0.5) + data->m12 * (x + 0.5) + data->dy; |
| t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off; |
| t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off; |
| inc = op->linear.dx * data->m11 + op->linear.dy * data->m12; |
| inc = op->linear.dx * data->m11 + op->linear.dy * data->m12; |
| affine = !data->m13 && !data->m23; |
| affine = !data->m13 && !data->m23; |
| |
| |
| if (affine) { |
| if (affine) { |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| inc *= (GRADIENT_STOPTABLE_SIZE - 1); |
| inc *= (GRADIENT_STOPTABLE_SIZE - 1); |
| } |
| } |
| } |
| } |
| |
| |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| if (affine) { |
| if (affine) { |
| if (inc > -1e-5 && inc < 1e-5) { |
| if (inc > -1e-5 && inc < 1e-5) { |
| QT_MEMFILL_UINT(buffer, length, qt_gradient_pixel_fixed(&data->gradient, int(t * FIXPT_SIZE))); |
| QT_MEMFILL_UINT(buffer, length, qt_gradient_pixel_fixed(&data->gradient, int(t * FIXPT_SIZE))); |
| } else { |
| } else { |
| if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) && |
| if (t+inc*length < qreal(INT_MAX >> (FIXPT_BITS + 1)) && |
| t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) { |
| t+inc*length > qreal(INT_MIN >> (FIXPT_BITS + 1))) { |
| // we can use fixed point math |
| // we can use fixed point math |
| int t_fixed = int(t * FIXPT_SIZE); |
| int t_fixed = int(t * FIXPT_SIZE); |
| int inc_fixed = int(inc * FIXPT_SIZE); |
| int inc_fixed = int(inc * FIXPT_SIZE); |
| while (buffer < end) { |
| while (buffer < end) { |
| *buffer = qt_gradient_pixel_fixed(&data->gradient, t_fixed); |
| *buffer = qt_gradient_pixel_fixed(&data->gradient, t_fixed); |
| t_fixed += inc_fixed; |
| t_fixed += inc_fixed; |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } else { |
| } else { |
| // we have to fall back to float math |
| // we have to fall back to float math |
| while (buffer < end) { |
| while (buffer < end) { |
| *buffer = qt_gradient_pixel(&data->gradient, t/GRADIENT_STOPTABLE_SIZE); |
| *buffer = qt_gradient_pixel(&data->gradient, t/GRADIENT_STOPTABLE_SIZE); |
| t += inc; |
| t += inc; |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } |
| } |
| } |
| } |
| } else { // fall back to float math here as well |
| } else { // fall back to float math here as well |
| qreal rw = data->m23 * (y + 0.5) + data->m13 * (x + 0.5) + data->m33; |
| qreal rw = data->m23 * (y + 0.5) + data->m13 * (x + 0.5) + data->m33; |
| while (buffer < end) { |
| while (buffer < end) { |
| qreal x = rx/rw; |
| qreal x = rx/rw; |
| qreal y = ry/rw; |
| qreal y = ry/rw; |
| t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off; |
| t = (op->linear.dx*x + op->linear.dy *y) + op->linear.off; |
| |
| |
| *buffer = qt_gradient_pixel(&data->gradient, t); |
| *buffer = qt_gradient_pixel(&data->gradient, t); |
| rx += data->m11; |
| rx += data->m11; |
| ry += data->m12; |
| ry += data->m12; |
| rw += data->m13; |
| rw += data->m13; |
| if (!rw) { |
| if (!rw) { |
| rw += data->m13; |
| rw += data->m13; |
| } |
| } |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } |
| } |
| |
| |
| return b; |
| return b; |
| } |
| } |
| |
| |
| static inline qreal determinant(qreal a, qreal b, qreal c) |
| static inline qreal determinant(qreal a, qreal b, qreal c) |
| { |
| { |
| return (b * b) - (4 * a * c); |
| return (b * b) - (4 * a * c); |
| } |
| } |
| |
| |
| // function to evaluate real roots |
| // function to evaluate real roots |
| static inline qreal realRoots(qreal a, qreal b, qreal detSqrt) |
| static inline qreal realRoots(qreal a, qreal b, qreal detSqrt) |
| { |
| { |
| return (-b + detSqrt)/(2 * a); |
| return (-b + detSqrt)/(2 * a); |
| } |
| } |
| |
| |
| static inline qreal qSafeSqrt(qreal x) |
| static inline qreal qSafeSqrt(qreal x) |
| { |
| { |
| return x > 0 ? qSqrt(x) : 0; |
| return x > 0 ? qSqrt(x) : 0; |
| } |
| } |
| |
| |
| static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data) |
| static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data) |
| { |
| { |
| v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; |
| v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; |
| v->dy = data->gradient.radial.center.y - data->gradient.radial.focal.y; |
| v->dy = data->gradient.radial.center.y - data->gradient.radial.focal.y; |
| v->a = data->gradient.radial.radius*data->gradient.radial.radius - v->dx*v->dx - v->dy*v->dy; |
| v->a = data->gradient.radial.radius*data->gradient.radial.radius - v->dx*v->dx - v->dy*v->dy; |
| } |
| } |
| |
| |
| static const uint * QT_FASTCALL fetchRadialGradient(uint *buffer, const Operator *op, const QSpanData *data, |
| static const uint * QT_FASTCALL fetchRadialGradient(uint *buffer, const Operator *op, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| const uint *b = buffer; |
| const uint *b = buffer; |
| qreal rx = data->m21 * (y + 0.5) |
| qreal rx = data->m21 * (y + 0.5) |
| + data->dx + data->m11 * (x + 0.5); |
| + data->dx + data->m11 * (x + 0.5); |
| qreal ry = data->m22 * (y + 0.5) |
| qreal ry = data->m22 * (y + 0.5) |
| + data->dy + data->m12 * (x + 0.5); |
| + data->dy + data->m12 * (x + 0.5); |
| bool affine = !data->m13 && !data->m23; |
| bool affine = !data->m13 && !data->m23; |
| //qreal r = data->gradient.radial.radius; |
| //qreal r = data->gradient.radial.radius; |
| |
| |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| if (affine) { |
| if (affine) { |
| rx -= data->gradient.radial.focal.x; |
| rx -= data->gradient.radial.focal.x; |
| ry -= data->gradient.radial.focal.y; |
| ry -= data->gradient.radial.focal.y; |
| |
| |
| qreal inv_a = 1 / qreal(2 * op->radial.a); |
| qreal inv_a = 1 / qreal(2 * op->radial.a); |
| |
| |
| const qreal delta_rx = data->m11; |
| const qreal delta_rx = data->m11; |
| const qreal delta_ry = data->m12; |
| const qreal delta_ry = data->m12; |
| |
| |
| qreal b = 2*(rx * op->radial.dx + ry * op->radial.dy); |
| qreal b = 2*(rx * op->radial.dx + ry * op->radial.dy); |
| qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy); |
| qreal delta_b = 2*(delta_rx * op->radial.dx + delta_ry * op->radial.dy); |
| const qreal b_delta_b = 2 * b * delta_b; |
| const qreal b_delta_b = 2 * b * delta_b; |
| const qreal delta_b_delta_b = 2 * delta_b * delta_b; |
| const qreal delta_b_delta_b = 2 * delta_b * delta_b; |
| |
| |
| const qreal bb = b * b; |
| const qreal bb = b * b; |
| const qreal delta_bb = delta_b * delta_b; |
| const qreal delta_bb = delta_b * delta_b; |
| |
| |
| b *= inv_a; |
| b *= inv_a; |
| delta_b *= inv_a; |
| delta_b *= inv_a; |
| |
| |
| const qreal rxrxryry = rx * rx + ry * ry; |
| const qreal rxrxryry = rx * rx + ry * ry; |
| const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry; |
| const qreal delta_rxrxryry = delta_rx * delta_rx + delta_ry * delta_ry; |
| const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry); |
| const qreal rx_plus_ry = 2*(rx * delta_rx + ry * delta_ry); |
| const qreal delta_rx_plus_ry = 2 * delta_rxrxryry; |
| const qreal delta_rx_plus_ry = 2 * delta_rxrxryry; |
| |
| |
| inv_a *= inv_a; |
| inv_a *= inv_a; |
| |
| |
| qreal det = (bb + 4 * op->radial.a * rxrxryry) * inv_a; |
| qreal det = (bb + 4 * op->radial.a * rxrxryry) * inv_a; |
| qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a; |
| qreal delta_det = (b_delta_b + delta_bb + 4 * op->radial.a * (rx_plus_ry + delta_rxrxryry)) * inv_a; |
| const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a; |
| const qreal delta_delta_det = (delta_b_delta_b + 4 * op->radial.a * delta_rx_plus_ry) * inv_a; |
| |
| |
| while (buffer < end) { |
| while (buffer < end) { |
| *buffer = qt_gradient_pixel(&data->gradient, qSafeSqrt(det) - b); |
| *buffer = qt_gradient_pixel(&data->gradient, qSafeSqrt(det) - b); |
| |
| |
| det += delta_det; |
| det += delta_det; |
| delta_det += delta_delta_det; |
| delta_det += delta_delta_det; |
| b += delta_b; |
| b += delta_b; |
| |
| |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } else { |
| } else { |
| qreal rw = data->m23 * (y + 0.5) |
| qreal rw = data->m23 * (y + 0.5) |
| + data->m33 + data->m13 * (x + 0.5); |
| + data->m33 + data->m13 * (x + 0.5); |
| if (!rw) |
| if (!rw) |
| rw = 1; |
| rw = 1; |
| while (buffer < end) { |
| while (buffer < end) { |
| qreal gx = rx/rw - data->gradient.radial.focal.x; |
| qreal gx = rx/rw - data->gradient.radial.focal.x; |
| qreal gy = ry/rw - data->gradient.radial.focal.y; |
| qreal gy = ry/rw - data->gradient.radial.focal.y; |
| qreal b = 2*(gx*op->radial.dx + gy*op->radial.dy); |
| qreal b = 2*(gx*op->radial.dx + gy*op->radial.dy); |
| qreal det = determinant(op->radial.a, b , -(gx*gx + gy*gy)); |
| qreal det = determinant(op->radial.a, b , -(gx*gx + gy*gy)); |
| qreal s = realRoots(op->radial.a, b, qSafeSqrt(det)); |
| qreal s = realRoots(op->radial.a, b, qSafeSqrt(det)); |
| |
| |
| *buffer = qt_gradient_pixel(&data->gradient, s); |
| *buffer = qt_gradient_pixel(&data->gradient, s); |
| |
| |
| rx += data->m11; |
| rx += data->m11; |
| ry += data->m12; |
| ry += data->m12; |
| rw += data->m13; |
| rw += data->m13; |
| if (!rw) { |
| if (!rw) { |
| rw += data->m13; |
| rw += data->m13; |
| } |
| } |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } |
| } |
| |
| |
| return b; |
| return b; |
| } |
| } |
| |
| |
| static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operator *, const QSpanData *data, |
| static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operator *, const QSpanData *data, |
| int y, int x, int length) |
| int y, int x, int length) |
| { |
| { |
| const uint *b = buffer; |
| const uint *b = buffer; |
| qreal rx = data->m21 * (y + 0.5) |
| qreal rx = data->m21 * (y + 0.5) |
| + data->dx + data->m11 * (x + 0.5); |
| + data->dx + data->m11 * (x + 0.5); |
| qreal ry = data->m22 * (y + 0.5) |
| qreal ry = data->m22 * (y + 0.5) |
| + data->dy + data->m12 * (x + 0.5); |
| + data->dy + data->m12 * (x + 0.5); |
| bool affine = !data->m13 && !data->m23; |
| bool affine = !data->m13 && !data->m23; |
| |
| |
| const uint *end = buffer + length; |
| const uint *end = buffer + length; |
| if (affine) { |
| if (affine) { |
| rx -= data->gradient.conical.center.x; |
| rx -= data->gradient.conical.center.x; |
| ry -= data->gradient.conical.center.y; |
| ry -= data->gradient.conical.center.y; |
| while (buffer < end) { |
| while (buffer < end) { |
| qreal angle = qAtan2(ry, rx) + data->gradient.conical.angle; |
| qreal angle = qAtan2(ry, rx) + data->gradient.conical.angle; |
| |
| |
| *buffer = qt_gradient_pixel(&data->gradient, 1 - angle / (2*Q_PI)); |
| *buffer = qt_gradient_pixel(&data->gradient, 1 - angle / (2*Q_PI)); |
| |
| |
| rx += data->m11; |
| rx += data->m11; |
| ry += data->m12; |
| ry += data->m12; |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } else { |
| } else { |
| qreal rw = data->m23 * (y + 0.5) |
| qreal rw = data->m23 * (y + 0.5) |
| + data->m33 + data->m13 * (x + 0.5); |
| + data->m33 + data->m13 * (x + 0.5); |
| if (!rw) |
| if (!rw) |
| rw = 1; |
| rw = 1; |
| while (buffer < end) { |
| while (buffer < end) { |
| qreal angle = qAtan2(ry/rw - data->gradient.conical.center.x, |
| qreal angle = qAtan2(ry/rw - data->gradient.conical.center.x, |
| rx/rw - data->gradient.conical.center.y) |
| rx/rw - data->gradient.conical.center.y) |
| + data->gradient.conical.angle; |
| + data->gradient.conical.angle; |
| |
| |
| *buffer = qt_gradient_pixel(&data->gradient, 1. - angle / (2*Q_PI)); |
| *buffer = qt_gradient_pixel(&data->gradient, 1. - angle / (2*Q_PI)); |
| |
| |
| rx += data->m11; |
| rx += data->m11; |
| ry += data->m12; |
| ry += data->m12; |
| rw += data->m13; |
| rw += data->m13; |
| if (!rw) { |
| if (!rw) { |
| rw += data->m13; |
| rw += data->m13; |
| } |
| } |
| ++buffer; |
| ++buffer; |
| } |
| } |
| } |
| } |
| return b; |
| return b; |
| } |
| } |
| |
| |
| #if defined(Q_CC_RVCT) |
| #if defined(Q_CC_RVCT) |
| // Force ARM code generation for comp_func_* -methods |
| // Force ARM code generation for comp_func_* -methods |
| # pragma push |
| # pragma push |
| # pragma arm |
| # pragma arm |
| # if defined(QT_HAVE_ARMV6) |
| # if defined(QT_HAVE_ARMV6) |
| static __forceinline void preload(const uint *start) |
| static __forceinline void preload(const uint *start) |
| { |
| { |
| asm( "pld [start]" ); |
| asm( "pld [start]" ); |
| } |
| } |
| static const uint L2CacheLineLength = 32; |
| static const uint L2CacheLineLength = 32; |
| static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint); |
| static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint); |
| # define PRELOAD_INIT(x) preload(x); |
| # define PRELOAD_INIT(x) preload(x); |
| # define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y) |
| # define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y) |
| # define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); |
| # define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); |
| // Two consecutive preloads stall, so space them out a bit by using different modulus. |
| // Two consecutive preloads stall, so space them out a bit by using different modulus. |
| # define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \ |
| # define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \ |
| if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts); |
| if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts); |
| # endif // QT_HAVE_ARMV6 |
| # endif // QT_HAVE_ARMV6 |
| #endif // Q_CC_RVCT |
| #endif // Q_CC_RVCT |
| |
| |
| #if !defined(Q_CC_RVCT) || !defined(QT_HAVE_ARMV6) |
| #if !defined(Q_CC_RVCT) || !defined(QT_HAVE_ARMV6) |
| # define PRELOAD_INIT(x) |
| # define PRELOAD_INIT(x) |
| # define PRELOAD_INIT2(x,y) |
| # define PRELOAD_INIT2(x,y) |
| # define PRELOAD_COND(x) |
| # define PRELOAD_COND(x) |
| # define PRELOAD_COND2(x,y) |
| # define PRELOAD_COND2(x,y) |
| #endif |
| #endif |
| |
| |
| /* The constant alpha factor describes an alpha factor that gets applied |
| /* The constant alpha factor describes an alpha factor that gets applied |
| to the result of the composition operation combining it with the destination. |
| to the result of the composition operation combining it with the destination. |
| |
| |
| The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1. |
| The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1. |
| we get the unmodified operation |
| we get the unmodified operation |
| |
| |
| result = src op dest |
| result = src op dest |
| dest = result * const_alpha + dest * (1. - const_alpha) |
| dest = result * const_alpha + dest * (1. - const_alpha) |
| |
| |
| This means that in the comments below, the first line is the const_alpha==255 case, the |
| This means that in the comments below, the first line is the const_alpha==255 case, the |
| second line the general one. |
| second line the general one. |
| |
| |
| In the lines below: |
| In the lines below: |
| s == src, sa == alpha(src), sia = 1 - alpha(src) |
| s == src, sa == alpha(src), sia = 1 - alpha(src) |
| d == dest, da == alpha(dest), dia = 1 - alpha(dest) |
| d == dest, da == alpha(dest), dia = 1 - alpha(dest) |
| ca = const_alpha, cia = 1 - const_alpha |
| ca = const_alpha, cia = 1 - const_alpha |
| |
| |
| The methods exist in two variants. One where we have a constant source, the other |
| The methods exist in two variants. One where we have a constant source, the other |
| where the source is an array of pixels. |
| where the source is an array of pixels. |
| */ |
| */ |
| |
| |
| /* |
| /* |
| result = 0 |
| result = 0 |
| d = d * cia |
| d = d * cia |
| */ |
| */ |
| #define comp_func_Clear_impl(dest, length, const_alpha)\ |
| #define comp_func_Clear_impl(dest, length, const_alpha)\ |
| {\ |
| {\ |
| if (const_alpha == 255) {\ |
| if (const_alpha == 255) {\ |
| QT_MEMFILL_UINT(dest, length, 0);\ |
| QT_MEMFILL_UINT(dest, length, 0);\ |
| } else {\ |
| } else {\ |
| int ialpha = 255 - const_alpha;\ |
| int ialpha = 255 - const_alpha;\ |
| PRELOAD_INIT(dest)\ |
| PRELOAD_INIT(dest)\ |
| for (int i = 0; i < length; ++i) {\ |
| for (int i = 0; i < length; ++i) {\ |
| PRELOAD_COND(dest)\ |
| PRELOAD_COND(dest)\ |
| dest[i] = BYTE_MUL(dest[i], ialpha);\ |
| dest[i] = BYTE_MUL(dest[i], ialpha);\ |
| }\ |
| }\ |
| }\ |
| }\ |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha) |
| { |
| { |
| comp_func_Clear_impl(dest, length, const_alpha); |
| comp_func_Clear_impl(dest, length, const_alpha); |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha) |
| { |
| { |
| comp_func_Clear_impl(dest, length, const_alpha); |
| comp_func_Clear_impl(dest, length, const_alpha); |
| } |
| } |
| |
| |
| /* |
| /* |
| result = s |
| result = s |
| dest = s * ca + d * cia |
| dest = s * ca + d * cia |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| QT_MEMFILL_UINT(dest, length, color); |
| QT_MEMFILL_UINT(dest, length, color); |
| } else { |
| } else { |
| int ialpha = 255 - const_alpha; |
| int ialpha = 255 - const_alpha; |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = color + BYTE_MUL(dest[i], ialpha); |
| dest[i] = color + BYTE_MUL(dest[i], ialpha); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| ::memcpy(dest, src, length * sizeof(uint)); |
| ::memcpy(dest, src, length * sizeof(uint)); |
| } else { |
| } else { |
| int ialpha = 255 - const_alpha; |
| int ialpha = 255 - const_alpha; |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); |
| dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) |
| void QT_FASTCALL comp_func_solid_Destination(uint *, int, uint, uint) |
| { |
| { |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint) |
| void QT_FASTCALL comp_func_Destination(uint *, const uint *, int, uint) |
| { |
| { |
| } |
| } |
| |
| |
| /* |
| /* |
| result = s + d * sia |
| result = s + d * sia |
| dest = (s + d * sia) * ca + d * cia |
| dest = (s + d * sia) * ca + d * cia |
| = s * ca + d * (sia * ca + cia) |
| = s * ca + d * (sia * ca + cia) |
| = s * ca + d * (1 - sa*ca) |
| = s * ca + d * (1 - sa*ca) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if ((const_alpha & qAlpha(color)) == 255) { |
| if ((const_alpha & qAlpha(color)) == 255) { |
| QT_MEMFILL_UINT(dest, length, color); |
| QT_MEMFILL_UINT(dest, length, color); |
| } else { |
| } else { |
| if (const_alpha != 255) |
| if (const_alpha != 255) |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); |
| dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = src[i]; |
| uint s = src[i]; |
| if (s >= 0xff000000) |
| if (s >= 0xff000000) |
| dest[i] = s; |
| dest[i] = s; |
| else if (s != 0) |
| else if (s != 0) |
| dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); |
| dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); |
| dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = d + s * dia |
| result = d + s * dia |
| dest = (d + s * dia) * ca + d * cia |
| dest = (d + s * dia) * ca + d * cia |
| = d + s * dia * ca |
| = d + s * dia * ca |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha != 255) |
| if (const_alpha != 255) |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = d + BYTE_MUL(color, qAlpha(~d)); |
| dest[i] = d + BYTE_MUL(color, qAlpha(~d)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); |
| dest[i] = d + BYTE_MUL(src[i], qAlpha(~d)); |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| dest[i] = d + BYTE_MUL(s, qAlpha(~d)); |
| dest[i] = d + BYTE_MUL(s, qAlpha(~d)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = s * da |
| result = s * da |
| dest = s * da * ca + d * cia |
| dest = s * da * ca + d * cia |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = BYTE_MUL(color, qAlpha(dest[i])); |
| dest[i] = BYTE_MUL(color, qAlpha(dest[i])); |
| } |
| } |
| } else { |
| } else { |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| uint cia = 255 - const_alpha; |
| uint cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); |
| dest[i] = BYTE_MUL(src[i], qAlpha(dest[i])); |
| } |
| } |
| } else { |
| } else { |
| uint cia = 255 - const_alpha; |
| uint cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = d * sa |
| result = d * sa |
| dest = d * sa * ca + d * cia |
| dest = d * sa * ca + d * cia |
| = d * (sa * ca + cia) |
| = d * (sa * ca + cia) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| uint a = qAlpha(color); |
| uint a = qAlpha(color); |
| if (const_alpha != 255) { |
| if (const_alpha != 255) { |
| a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; |
| a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; |
| } |
| } |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = BYTE_MUL(dest[i], a); |
| dest[i] = BYTE_MUL(dest[i], a); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); |
| dest[i] = BYTE_MUL(dest[i], qAlpha(src[i])); |
| } |
| } |
| } else { |
| } else { |
| int cia = 255 - const_alpha; |
| int cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; |
| uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia; |
| dest[i] = BYTE_MUL(dest[i], a); |
| dest[i] = BYTE_MUL(dest[i], a); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = s * dia |
| result = s * dia |
| dest = s * dia * ca + d * cia |
| dest = s * dia * ca + d * cia |
| */ |
| */ |
| |
| |
| void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); |
| dest[i] = BYTE_MUL(color, qAlpha(~dest[i])); |
| } |
| } |
| } else { |
| } else { |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| int cia = 255 - const_alpha; |
| int cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); |
| dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i])); |
| } |
| } |
| } else { |
| } else { |
| int cia = 255 - const_alpha; |
| int cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = d * sia |
| result = d * sia |
| dest = d * sia * ca + d * cia |
| dest = d * sia * ca + d * cia |
| = d * (sia * ca + cia) |
| = d * (sia * ca + cia) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| uint a = qAlpha(~color); |
| uint a = qAlpha(~color); |
| if (const_alpha != 255) |
| if (const_alpha != 255) |
| a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; |
| a = BYTE_MUL(a, const_alpha) + 255 - const_alpha; |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = BYTE_MUL(dest[i], a); |
| dest[i] = BYTE_MUL(dest[i], a); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); |
| dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i])); |
| } |
| } |
| } else { |
| } else { |
| int cia = 255 - const_alpha; |
| int cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; |
| uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia; |
| dest[i] = BYTE_MUL(dest[i], sia); |
| dest[i] = BYTE_MUL(dest[i], sia); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = s*da + d*sia |
| result = s*da + d*sia |
| dest = s*da*ca + d*sia*ca + d *cia |
| dest = s*da*ca + d*sia*ca + d *cia |
| = s*ca * da + d * (sia*ca + cia) |
| = s*ca * da + d * (sia*ca + cia) |
| = s*ca * da + d * (1 - sa*ca) |
| = s*ca * da + d * (1 - sa*ca) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha != 255) { |
| if (const_alpha != 255) { |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| } |
| } |
| uint sia = qAlpha(~color); |
| uint sia = qAlpha(~color); |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = src[i]; |
| uint s = src[i]; |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = d*sa + s*dia |
| result = d*sa + s*dia |
| dest = d*sa*ca + s*dia*ca + d *cia |
| dest = d*sa*ca + s*dia*ca + d *cia |
| = s*ca * dia + d * (sa*ca + cia) |
| = s*ca * dia + d * (sa*ca + cia) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| uint a = qAlpha(color); |
| uint a = qAlpha(color); |
| if (const_alpha != 255) { |
| if (const_alpha != 255) { |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| a = qAlpha(color) + 255 - const_alpha; |
| a = qAlpha(color) + 255 - const_alpha; |
| } |
| } |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); |
| dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = src[i]; |
| uint s = src[i]; |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); |
| dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d)); |
| } |
| } |
| } else { |
| } else { |
| int cia = 255 - const_alpha; |
| int cia = 255 - const_alpha; |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint a = qAlpha(s) + cia; |
| uint a = qAlpha(s) + cia; |
| dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d)); |
| dest[i] = INTERPOLATE_PIXEL_255(d, a, s, qAlpha(~d)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /* |
| /* |
| result = d*sia + s*dia |
| result = d*sia + s*dia |
| dest = d*sia*ca + s*dia*ca + d *cia |
| dest = d*sia*ca + s*dia*ca + d *cia |
| = s*ca * dia + d * (sia*ca + cia) |
| = s*ca * dia + d * (sia*ca + cia) |
| = s*ca * dia + d * (1 - sa*ca) |
| = s*ca * dia + d * (1 - sa*ca) |
| */ |
| */ |
| void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha != 255) |
| if (const_alpha != 255) |
| color = BYTE_MUL(color, const_alpha); |
| color = BYTE_MUL(color, const_alpha); |
| uint sia = qAlpha(~color); |
| uint sia = qAlpha(~color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); |
| dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| if (const_alpha == 255) { |
| if (const_alpha == 255) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); |
| } |
| } |
| } else { |
| } else { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = BYTE_MUL(src[i], const_alpha); |
| uint s = BYTE_MUL(src[i], const_alpha); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); |
| dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| struct QFullCoverage { |
| struct QFullCoverage { |
| inline void store(uint *dest, const uint src) const |
| inline void store(uint *dest, const uint src) const |
| { |
| { |
| *dest = src; |
| *dest = src; |
| } |
| } |
| }; |
| }; |
| |
| |
| struct QPartialCoverage { |
| struct QPartialCoverage { |
| inline QPartialCoverage(uint const_alpha) |
| inline QPartialCoverage(uint const_alpha) |
| : ca(const_alpha) |
| : ca(const_alpha) |
| , ica(255 - const_alpha) |
| , ica(255 - const_alpha) |
| { |
| { |
| } |
| } |
| |
| |
| inline void store(uint *dest, const uint src) const |
| inline void store(uint *dest, const uint src) const |
| { |
| { |
| *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica); |
| *dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica); |
| } |
| } |
| |
| |
| private: |
| private: |
| const uint ca; |
| const uint ca; |
| const uint ica; |
| const uint ica; |
| }; |
| }; |
| |
| |
| static inline int mix_alpha(int da, int sa) |
| static inline int mix_alpha(int da, int sa) |
| { |
| { |
| return 255 - ((255 - sa) * (255 - da) >> 8); |
| return 255 - ((255 - sa) * (255 - da) >> 8); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa) |
| = Sca + Dca |
| = Sca + Dca |
| */ |
| */ |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| uint s = color; |
| uint s = color; |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| d = comp_func_Plus_one_pixel(d, s); |
| d = comp_func_Plus_one_pixel(d, s); |
| coverage.store(&dest[i], d); |
| coverage.store(&dest[i], d); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Plus_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Plus_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Plus_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| d = comp_func_Plus_one_pixel(d, s); |
| d = comp_func_Plus_one_pixel(d, s); |
| |
| |
| coverage.store(&dest[i], d); |
| coverage.store(&dest[i], d); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Plus(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Plus_impl(dest, src, length, QFullCoverage()); |
| comp_func_Plus_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Plus_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline int multiply_op(int dst, int src, int da, int sa) |
| static inline int multiply_op(int dst, int src, int da, int sa) |
| { |
| { |
| return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa)); |
| return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) multiply_op(a, b, da, sa) |
| #define OP(a, b) multiply_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) multiply_op(a, b, da, sa) |
| #define OP(a, b) multiply_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Multiply(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Multiply_impl(dest, src, length, QFullCoverage()); |
| comp_func_Multiply_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| = Sca + Dca - Sca.Dca |
| = Sca + Dca - Sca.Dca |
| */ |
| */ |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) 255 - qt_div_255((255-a) * (255-b)) |
| #define OP(a, b) 255 - qt_div_255((255-a) * (255-b)) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Screen_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Screen_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) 255 - (((255-a) * (255-b)) >> 8) |
| #define OP(a, b) 255 - (((255-a) * (255-b)) >> 8) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Screen_impl(dest, src, length, QFullCoverage()); |
| comp_func_Screen_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| if 2.Dca < Da |
| if 2.Dca < Da |
| Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise |
| otherwise |
| Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline int overlay_op(int dst, int src, int da, int sa) |
| static inline int overlay_op(int dst, int src, int da, int sa) |
| { |
| { |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| if (2 * dst < da) |
| if (2 * dst < da) |
| return qt_div_255(2 * src * dst + temp); |
| return qt_div_255(2 * src * dst + temp); |
| else |
| else |
| return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); |
| return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) overlay_op(a, b, da, sa) |
| #define OP(a, b) overlay_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) overlay_op(a, b, da, sa) |
| #define OP(a, b) overlay_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Overlay(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Overlay_impl(dest, src, length, QFullCoverage()); |
| comp_func_Overlay_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Da' = Sa + Da - Sa.Da |
| Da' = Sa + Da - Sa.Da |
| */ |
| */ |
| static inline int darken_op(int dst, int src, int da, int sa) |
| static inline int darken_op(int dst, int src, int da, int sa) |
| { |
| { |
| return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); |
| return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) darken_op(a, b, da, sa) |
| #define OP(a, b) darken_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Darken_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Darken_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) darken_op(a, b, da, sa) |
| #define OP(a, b) darken_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Darken(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Darken_impl(dest, src, length, QFullCoverage()); |
| comp_func_Darken_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Da' = Sa + Da - Sa.Da |
| Da' = Sa + Da - Sa.Da |
| */ |
| */ |
| static inline int lighten_op(int dst, int src, int da, int sa) |
| static inline int lighten_op(int dst, int src, int da, int sa) |
| { |
| { |
| return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); |
| return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) lighten_op(a, b, da, sa) |
| #define OP(a, b) lighten_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) lighten_op(a, b, da, sa) |
| #define OP(a, b) lighten_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Lighten(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Lighten_impl(dest, src, length, QFullCoverage()); |
| comp_func_Lighten_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| if Sca.Da + Dca.Sa >= Sa.Da |
| if Sca.Da + Dca.Sa >= Sa.Da |
| Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise |
| otherwise |
| Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline int color_dodge_op(int dst, int src, int da, int sa) |
| static inline int color_dodge_op(int dst, int src, int da, int sa) |
| { |
| { |
| const int sa_da = sa * da; |
| const int sa_da = sa * da; |
| const int dst_sa = dst * sa; |
| const int dst_sa = dst * sa; |
| const int src_da = src * da; |
| const int src_da = src * da; |
| |
| |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| if (src_da + dst_sa >= sa_da) |
| if (src_da + dst_sa >= sa_da) |
| return qt_div_255(sa_da + temp); |
| return qt_div_255(sa_da + temp); |
| else |
| else |
| return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp); |
| return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a,b) color_dodge_op(a, b, da, sa) |
| #define OP(a,b) color_dodge_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) color_dodge_op(a, b, da, sa) |
| #define OP(a, b) color_dodge_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_ColorDodge(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_ColorDodge_impl(dest, src, length, QFullCoverage()); |
| comp_func_ColorDodge_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| if Sca.Da + Dca.Sa <= Sa.Da |
| if Sca.Da + Dca.Sa <= Sa.Da |
| Dca' = Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise |
| otherwise |
| Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline int color_burn_op(int dst, int src, int da, int sa) |
| static inline int color_burn_op(int dst, int src, int da, int sa) |
| { |
| { |
| const int src_da = src * da; |
| const int src_da = src * da; |
| const int dst_sa = dst * sa; |
| const int dst_sa = dst * sa; |
| const int sa_da = sa * da; |
| const int sa_da = sa * da; |
| |
| |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| const int temp = src * (255 - da) + dst * (255 - sa); |
| |
| |
| if (src == 0 || src_da + dst_sa <= sa_da) |
| if (src == 0 || src_da + dst_sa <= sa_da) |
| return qt_div_255(temp); |
| return qt_div_255(temp); |
| return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp); |
| return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) color_burn_op(a, b, da, sa) |
| #define OP(a, b) color_burn_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) color_burn_op(a, b, da, sa) |
| #define OP(a, b) color_burn_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_ColorBurn(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_ColorBurn_impl(dest, src, length, QFullCoverage()); |
| comp_func_ColorBurn_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| if 2.Sca < Sa |
| if 2.Sca < Sa |
| Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise |
| otherwise |
| Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline uint hardlight_op(int dst, int src, int da, int sa) |
| static inline uint hardlight_op(int dst, int src, int da, int sa) |
| { |
| { |
| const uint temp = src * (255 - da) + dst * (255 - sa); |
| const uint temp = src * (255 - da) + dst * (255 - sa); |
| |
| |
| if (2 * src < sa) |
| if (2 * src < sa) |
| return qt_div_255(2 * src * dst + temp); |
| return qt_div_255(2 * src * dst + temp); |
| else |
| else |
| return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); |
| return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) hardlight_op(a, b, da, sa) |
| #define OP(a, b) hardlight_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) hardlight_op(a, b, da, sa) |
| #define OP(a, b) hardlight_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_HardLight(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_HardLight_impl(dest, src, length, QFullCoverage()); |
| comp_func_HardLight_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| if 2.Sca <= Sa |
| if 2.Sca <= Sa |
| Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise if 2.Sca > Sa and 4.Dca <= Da |
| otherwise if 2.Sca > Sa and 4.Dca <= Da |
| Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Dca.Sa + Da.(2.Sca - Sa).(4.Dca/Da.(4.Dca/Da + 1).(Dca/Da - 1) + 7.Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| otherwise if 2.Sca > Sa and 4.Dca > Da |
| otherwise if 2.Sca > Sa and 4.Dca > Da |
| Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| static inline int soft_light_op(int dst, int src, int da, int sa) |
| static inline int soft_light_op(int dst, int src, int da, int sa) |
| { |
| { |
| const int src2 = src << 1; |
| const int src2 = src << 1; |
| const int dst_np = da != 0 ? (255 * dst) / da : 0; |
| const int dst_np = da != 0 ? (255 * dst) / da : 0; |
| const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; |
| const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; |
| |
| |
| if (src2 < sa) |
| if (src2 < sa) |
| return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; |
| return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; |
| else if (4 * dst <= da) |
| else if (4 * dst <= da) |
| return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; |
| return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; |
| else { |
| else { |
| # ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 |
| # ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2 |
| return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025; |
| return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025; |
| # else |
| # else |
| return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; |
| return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; |
| # endif |
| # endif |
| } |
| } |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) soft_light_op(a, b, da, sa) |
| #define OP(a, b) soft_light_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) soft_light_op(a, b, da, sa) |
| #define OP(a, b) soft_light_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_SoftLight(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_SoftLight_impl(dest, src, length, QFullCoverage()); |
| comp_func_SoftLight_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
| = Sca + Dca - 2.min(Sca.Da, Dca.Sa) |
| = Sca + Dca - 2.min(Sca.Da, Dca.Sa) |
| */ |
| */ |
| static inline int difference_op(int dst, int src, int da, int sa) |
| static inline int difference_op(int dst, int src, int da, int sa) |
| { |
| { |
| return src + dst - qt_div_255(2 * qMin(src * da, dst * sa)); |
| return src + dst - qt_div_255(2 * qMin(src * da, dst * sa)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) difference_op(a, b, da, sa) |
| #define OP(a, b) difference_op(a, b, da, sa) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Difference_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Difference_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) difference_op(a, b, da, sa) |
| #define OP(a, b) difference_op(a, b, da, sa) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Difference(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Difference_impl(dest, src, length, QFullCoverage()); |
| comp_func_Difference_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| /* |
| /* |
| Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) |
| */ |
| */ |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(uint *dest, int length, uint color, const T &coverage) |
| { |
| { |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| PRELOAD_INIT(dest) |
| PRELOAD_INIT(dest) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND(dest) |
| PRELOAD_COND(dest) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| |
| |
| #define OP(a, b) (a + b - qt_div_255(2*(a*b))) |
| #define OP(a, b) (a + b - qt_div_255(2*(a*b))) |
| int r = OP( qRed(d), sr); |
| int r = OP( qRed(d), sr); |
| int b = OP( qBlue(d), sb); |
| int b = OP( qBlue(d), sb); |
| int g = OP(qGreen(d), sg); |
| int g = OP(qGreen(d), sg); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha) |
| void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage()); |
| comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage()); |
| else |
| else |
| comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage) |
| Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage) |
| { |
| { |
| PRELOAD_INIT2(dest, src) |
| PRELOAD_INIT2(dest, src) |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| PRELOAD_COND2(dest, src) |
| PRELOAD_COND2(dest, src) |
| uint d = dest[i]; |
| uint d = dest[i]; |
| uint s = src[i]; |
| uint s = src[i]; |
| |
| |
| int da = qAlpha(d); |
| int da = qAlpha(d); |
| int sa = qAlpha(s); |
| int sa = qAlpha(s); |
| |
| |
| #define OP(a, b) (a + b - ((a*b) >> 7)) |
| #define OP(a, b) (a + b - ((a*b) >> 7)) |
| int r = OP( qRed(d), qRed(s)); |
| int r = OP( qRed(d), qRed(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int b = OP( qBlue(d), qBlue(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int g = OP(qGreen(d), qGreen(s)); |
| int a = mix_alpha(da, sa); |
| int a = mix_alpha(da, sa); |
| #undef OP |
| #undef OP |
| |
| |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| coverage.store(&dest[i], qRgba(r, g, b, a)); |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha) |
| void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int length, uint const_alpha) |
| { |
| { |
| if (const_alpha == 255) |
| if (const_alpha == 255) |
| comp_func_Exclusion_impl(dest, src, length, QFullCoverage()); |
| comp_func_Exclusion_impl(dest, src, length, QFullCoverage()); |
| else |
| else |
| comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha)); |
| } |
| } |
| |
| |
| #if defined(Q_CC_RVCT) |
| #if defined(Q_CC_RVCT) |
| // Restore pragma state from previous #pragma arm |
| // Restore pragma state from previous #pragma arm |
| # pragma pop |
| # pragma pop |
| #endif |
| #endif |
| |
| |
| void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) |
| while (length--) |
| *dest++ |= color; |
| *dest++ |= color; |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, |
| void QT_FASTCALL rasterop_SourceOrDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) |
| while (length--) |
| *dest++ |= *src++; |
| *dest++ |= *src++; |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_SourceAndDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color |= 0xff000000; |
| color |= 0xff000000; |
| while (length--) |
| while (length--) |
| *dest++ &= color; |
| *dest++ &= color; |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, |
| void QT_FASTCALL rasterop_SourceAndDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (*src & *dest) | 0xff000000; |
| *dest = (*src & *dest) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_SourceXorDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color &= 0x00ffffff; |
| color &= 0x00ffffff; |
| while (length--) |
| while (length--) |
| *dest++ ^= color; |
| *dest++ ^= color; |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, |
| void QT_FASTCALL rasterop_SourceXorDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (*src ^ *dest) | 0xff000000; |
| *dest = (*src ^ *dest) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_NotSourceAndNotDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color = ~color; |
| color = ~color; |
| while (length--) { |
| while (length--) { |
| *dest = (color & ~(*dest)) | 0xff000000; |
| *dest = (color & ~(*dest)) | 0xff000000; |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_NotSourceAndNotDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (~(*src) & ~(*dest)) | 0xff000000; |
| *dest = (~(*src) & ~(*dest)) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_NotSourceOrNotDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color = ~color | 0xff000000; |
| color = ~color | 0xff000000; |
| while (length--) { |
| while (length--) { |
| *dest = color | ~(*dest); |
| *dest = color | ~(*dest); |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_NotSourceOrNotDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = ~(*src) | ~(*dest) | 0xff000000; |
| *dest = ~(*src) | ~(*dest) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_NotSourceXorDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color = ~color & 0x00ffffff; |
| color = ~color & 0x00ffffff; |
| while (length--) { |
| while (length--) { |
| *dest = color ^ (*dest); |
| *dest = color ^ (*dest); |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, |
| void QT_FASTCALL rasterop_NotSourceXorDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = ((~(*src)) ^ (*dest)) | 0xff000000; |
| *dest = ((~(*src)) ^ (*dest)) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, |
| void QT_FASTCALL rasterop_solid_NotSource(uint *dest, int length, |
| uint color, uint const_alpha) |
| uint color, uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| qt_memfill(dest, ~color | 0xff000000, length); |
| qt_memfill(dest, ~color | 0xff000000, length); |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, |
| void QT_FASTCALL rasterop_NotSource(uint *dest, const uint *src, |
| int length, uint const_alpha) |
| int length, uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) |
| while (length--) |
| *dest++ = ~(*src++) | 0xff000000; |
| *dest++ = ~(*src++) | 0xff000000; |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_NotSourceAndDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| color = ~color | 0xff000000; |
| color = ~color | 0xff000000; |
| while (length--) { |
| while (length--) { |
| *dest = color & *dest; |
| *dest = color & *dest; |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, |
| void QT_FASTCALL rasterop_NotSourceAndDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (~(*src) & *dest) | 0xff000000; |
| *dest = (~(*src) & *dest) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_solid_SourceAndNotDestination(uint *dest, |
| int length, |
| int length, |
| uint color, |
| uint color, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (color & ~(*dest)) | 0xff000000; |
| *dest = (color & ~(*dest)) | 0xff000000; |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| |
| |
| void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, |
| void QT_FASTCALL rasterop_SourceAndNotDestination(uint *dest, |
| const uint *src, |
| const uint *src, |
| int length, |
| int length, |
| uint const_alpha) |
| uint const_alpha) |
| { |
| { |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| while (length--) { |
| while (length--) { |
| *dest = (*src & ~(*dest)) | 0xff000000; |
| *dest = (*src & ~(*dest)) | 0xff000000; |
| ++dest; ++src; |
| ++dest; ++src; |
| } |
| } |
| } |
| } |
| |
| |
| static CompositionFunctionSolid functionForModeSolid_C[] = { |
| static CompositionFunctionSolid functionForModeSolid_C[] = { |
| comp_func_solid_SourceOver, |
| comp_func_solid_SourceOver, |
| comp_func_solid_DestinationOver, |
| comp_func_solid_DestinationOver, |
| comp_func_solid_Clear, |
| comp_func_solid_Clear, |
| comp_func_solid_Source, |
| comp_func_solid_Source, |
| comp_func_solid_Destination, |
| comp_func_solid_Destination, |
| comp_func_solid_SourceIn, |
| comp_func_solid_SourceIn, |
| comp_func_solid_DestinationIn, |
| comp_func_solid_DestinationIn, |
| comp_func_solid_SourceOut, |
| comp_func_solid_SourceOut, |
| comp_func_solid_DestinationOut, |
| comp_func_solid_DestinationOut, |
| comp_func_solid_SourceAtop, |
| comp_func_solid_SourceAtop, |
| comp_func_solid_DestinationAtop, |
| comp_func_solid_DestinationAtop, |
| comp_func_solid_XOR, |
| comp_func_solid_XOR, |
| comp_func_solid_Plus, |
| comp_func_solid_Plus, |
| comp_func_solid_Multiply, |
| comp_func_solid_Multiply, |
| comp_func_solid_Screen, |
| comp_func_solid_Screen, |
| comp_func_solid_Overlay, |
| comp_func_solid_Overlay, |
| comp_func_solid_Darken, |
| comp_func_solid_Darken, |
| comp_func_solid_Lighten, |
| comp_func_solid_Lighten, |
| comp_func_solid_ColorDodge, |
| comp_func_solid_ColorDodge, |
| comp_func_solid_ColorBurn, |
| comp_func_solid_ColorBurn, |
| comp_func_solid_HardLight, |
| comp_func_solid_HardLight, |
| comp_func_solid_SoftLight, |
| comp_func_solid_SoftLight, |
| comp_func_solid_Difference, |
| comp_func_solid_Difference, |
| comp_func_solid_Exclusion, |
| comp_func_solid_Exclusion, |
| rasterop_solid_SourceOrDestination, |
| rasterop_solid_SourceOrDestination, |
| rasterop_solid_SourceAndDestination, |
| rasterop_solid_SourceAndDestination, |
| rasterop_solid_SourceXorDestination, |
| rasterop_solid_SourceXorDestination, |
| rasterop_solid_NotSourceAndNotDestination, |
| rasterop_solid_NotSourceAndNotDestination, |
| rasterop_solid_NotSourceOrNotDestination, |
| rasterop_solid_NotSourceOrNotDestination, |
| rasterop_solid_NotSourceXorDestination, |
| rasterop_solid_NotSourceXorDestination, |
| rasterop_solid_NotSource, |
| rasterop_solid_NotSource, |
| rasterop_solid_NotSourceAndDestination, |
| rasterop_solid_NotSourceAndDestination, |
| rasterop_solid_SourceAndNotDestination |
| rasterop_solid_SourceAndNotDestination |
| }; |
| }; |
| |
| |
| static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C; |
| static const CompositionFunctionSolid *functionForModeSolid = functionForModeSolid_C; |
| |
| |
| static CompositionFunction functionForMode_C[] = { |
| static CompositionFunction functionForMode_C[] = { |
| comp_func_SourceOver, |
| comp_func_SourceOver, |
| comp_func_DestinationOver, |
| comp_func_DestinationOver, |
| comp_func_Clear, |
| comp_func_Clear, |
| comp_func_Source, |
| comp_func_Source, |
| comp_func_Destination, |
| comp_func_Destination, |
| comp_func_SourceIn, |
| comp_func_SourceIn, |
| comp_func_DestinationIn, |
| comp_func_DestinationIn, |
| comp_func_SourceOut, |
| comp_func_SourceOut, |
| comp_func_DestinationOut, |
| comp_func_DestinationOut, |
| comp_func_SourceAtop, |
| comp_func_SourceAtop, |
| comp_func_DestinationAtop, |
| comp_func_DestinationAtop, |
| comp_func_XOR, |
| comp_func_XOR, |
| comp_func_Plus, |
| comp_func_Plus, |
| comp_func_Multiply, |
| comp_func_Multiply, |
| comp_func_Screen, |
| comp_func_Screen, |
| comp_func_Overlay, |
| comp_func_Overlay, |
| comp_func_Darken, |
| comp_func_Darken, |
| comp_func_Lighten, |
| comp_func_Lighten, |
| comp_func_ColorDodge, |
| comp_func_ColorDodge, |
| comp_func_ColorBurn, |
| comp_func_ColorBurn, |
| comp_func_HardLight, |
| comp_func_HardLight, |
| comp_func_SoftLight, |
| comp_func_SoftLight, |
| comp_func_Difference, |
| comp_func_Difference, |
| comp_func_Exclusion, |
| comp_func_Exclusion, |
| rasterop_SourceOrDestination, |
| rasterop_SourceOrDestination, |
| rasterop_SourceAndDestination, |
| rasterop_SourceAndDestination, |
| rasterop_SourceXorDestination, |
| rasterop_SourceXorDestination, |
| rasterop_NotSourceAndNotDestination, |
| rasterop_NotSourceAndNotDestination, |
| rasterop_NotSourceOrNotDestination, |
| rasterop_NotSourceOrNotDestination, |
| rasterop_NotSourceXorDestination, |
| rasterop_NotSourceXorDestination, |
| rasterop_NotSource, |
| rasterop_NotSource, |
| rasterop_NotSourceAndDestination, |
| rasterop_NotSourceAndDestination, |
| rasterop_SourceAndNotDestination |
| rasterop_SourceAndNotDestination |
| }; |
| }; |
| |
| |
| static const CompositionFunction *functionForMode = functionForMode_C; |
| static const CompositionFunction *functionForMode = functionForMode_C; |
| |
| |
| static TextureBlendType getBlendType(const QSpanData *data) |
| static TextureBlendType getBlendType(const QSpanData *data) |
| { |
| { |
| TextureBlendType ft; |
| TextureBlendType ft; |
| if (data->txop <= QTransform::TxTranslate) |
| if (data->txop <= QTransform::TxTranslate) |
| if (data->texture.type == QTextureData::Tiled) |
| if (data->texture.type == QTextureData::Tiled) |
| ft = BlendTiled; |
| ft = BlendTiled; |
| else |
| else |
| ft = BlendUntransformed; |
| ft = BlendUntransformed; |
| else if (data->bilinear) |
| else if (data->bilinear) |
| if (data->texture.type == QTextureData::Tiled) |
| if (data->texture.type == QTextureData::Tiled) |
| ft = BlendTransformedBilinearTiled; |
| ft = BlendTransformedBilinearTiled; |
| else |
| else |
| ft = BlendTransformedBilinear; |
| ft = BlendTransformedBilinear; |
| else |
| else |
| if (data->texture.type == QTextureData::Tiled) |
| if (data->texture.type == QTextureData::Tiled) |
| ft = BlendTransformedTiled; |
| ft = BlendTransformedTiled; |
| else |
| else |
| ft = BlendTransformed; |
| ft = BlendTransformed; |
| return ft; |
| return ft; |
| } |
| } |
| |
| |
| static inline Operator getOperator(const QSpanData *data, const QSpan *spans, int spanCount) |
| static inline Operator getOperator(const QSpanData *data, const QSpan *spans, int spanCount) |
| { |
| { |
| Operator op; |
| Operator op; |
| bool solidSource = false; |
| bool solidSource = false; |
| |
| |
| switch(data->type) { |
| switch(data->type) { |
| case QSpanData::Solid: |
| case QSpanData::Solid: |
| solidSource = (qAlpha(data->solid.color) == 255); |
| solidSource = (qAlpha(data->solid.color) == 255); |
| break; |
| break; |
| case QSpanData::LinearGradient: |
| case QSpanData::LinearGradient: |
| solidSource = !data->gradient.alphaColor; |
| solidSource = !data->gradient.alphaColor; |
| getLinearGradientValues(&op.linear, data); |
| getLinearGradientValues(&op.linear, data); |
| op.src_fetch = fetchLinearGradient; |
| op.src_fetch = fetchLinearGradient; |
| break; |
| break; |
| case QSpanData::RadialGradient: |
| case QSpanData::RadialGradient: |
| solidSource = !data->gradient.alphaColor; |
| solidSource = !data->gradient.alphaColor; |
| getRadialGradientValues(&op.radial, data); |
| getRadialGradientValues(&op.radial, data); |
| op.src_fetch = fetchRadialGradient; |
| op.src_fetch = fetchRadialGradient; |
| break; |
| break; |
| case QSpanData::ConicalGradient: |
| case QSpanData::ConicalGradient: |
| solidSource = !data->gradient.alphaColor; |
| solidSource = !data->gradient.alphaColor; |
| op.src_fetch = fetchConicalGradient; |
| op.src_fetch = fetchConicalGradient; |
| break; |
| break; |
| case QSpanData::Texture: |
| case QSpanData::Texture: |
| op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format]; |
| op.src_fetch = sourceFetch[getBlendType(data)][data->texture.format]; |
| solidSource = !data->texture.hasAlpha; |
| solidSource = !data->texture.hasAlpha; |
| default: |
| default: |
| break; |
| break; |
| } |
| } |
| |
| |
| op.mode = data->rasterBuffer->compositionMode; |
| op.mode = data->rasterBuffer->compositionMode; |
| if (op.mode == QPainter::CompositionMode_SourceOver && solidSource) |
| if (op.mode == QPainter::CompositionMode_SourceOver && solidSource) |
| op.mode = QPainter::CompositionMode_Source; |
| op.mode = QPainter::CompositionMode_Source; |
| |
| |
| op.dest_fetch = destFetchProc[data->rasterBuffer->format]; |
| op.dest_fetch = destFetchProc[data->rasterBuffer->format]; |
| if (op.mode == QPainter::CompositionMode_Source) { |
| if (op.mode == QPainter::CompositionMode_Source) { |
| switch (data->rasterBuffer->format) { |
| switch (data->rasterBuffer->format) { |
| case QImage::Format_RGB32: |
| case QImage::Format_RGB32: |
| case QImage::Format_ARGB32_Premultiplied: |
| case QImage::Format_ARGB32_Premultiplied: |
| // don't clear dest_fetch as it sets up the pointer correctly to save one copy |
| // don't clear dest_fetch as it sets up the pointer correctly to save one copy |
| break; |
| break; |
| default: { |
| default: { |
| const QSpan *lastSpan = spans + spanCount; |
| const QSpan *lastSpan = spans + spanCount; |
| bool alphaSpans = false; |
| bool alphaSpans = false; |
| while (spans < lastSpan) { |
| while (spans < lastSpan) { |
| if (spans->coverage != 255) { |
| if (spans->coverage != 255) { |
| alphaSpans = true; |
| alphaSpans = true; |
| break; |
| break; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| if (!alphaSpans) |
| if (!alphaSpans) |
| op.dest_fetch = 0; |
| op.dest_fetch = 0; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| op.dest_store = destStoreProc[data->rasterBuffer->format]; |
| op.dest_store = destStoreProc[data->rasterBuffer->format]; |
| |
| |
| op.funcSolid = functionForModeSolid[op.mode]; |
| op.funcSolid = functionForModeSolid[op.mode]; |
| op.func = functionForMode[op.mode]; |
| op.func = functionForMode[op.mode]; |
| |
| |
| return op; |
| return op; |
| } |
| } |
| |
| |
| |
| |
| |
| |
| // -------------------- blend methods --------------------- |
| // -------------------- blend methods --------------------- |
| |
| |
| enum SpanMethod { |
| enum SpanMethod { |
| RegularSpans, |
| RegularSpans, |
| CallbackSpans |
| CallbackSpans |
| }; |
| }; |
| |
| |
| #if !defined(Q_CC_SUN) |
| #if !defined(Q_CC_SUN) |
| static |
| static |
| #endif |
| #endif |
| void drawBufferSpan(QSpanData *data, const uint *buffer, int bufsize, |
| void drawBufferSpan(QSpanData *data, const uint *buffer, int bufsize, |
| int x, int y, int length, uint const_alpha) |
| int x, int y, int length, uint const_alpha) |
| { |
| { |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| data->rasterEngine->drawBufferSpan(buffer, bufsize, x, y, length, const_alpha); |
| data->rasterEngine->drawBufferSpan(buffer, bufsize, x, y, length, const_alpha); |
| #else |
| #else |
| Q_UNUSED(data); |
| Q_UNUSED(data); |
| Q_UNUSED(buffer); |
| Q_UNUSED(buffer); |
| Q_UNUSED(bufsize); |
| Q_UNUSED(bufsize); |
| Q_UNUSED(x); |
| Q_UNUSED(x); |
| Q_UNUSED(y); |
| Q_UNUSED(y); |
| Q_UNUSED(length); |
| Q_UNUSED(length); |
| Q_UNUSED(const_alpha); |
| Q_UNUSED(const_alpha); |
| #endif |
| #endif |
| } |
| } |
| |
| |
| #if !defined(Q_CC_SUN) |
| #if !defined(Q_CC_SUN) |
| static |
| static |
| #endif |
| #endif |
| void blend_color_generic(int count, const QSpan *spans, void *userData) |
| void blend_color_generic(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| while (count--) { |
| while (count--) { |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| int l = qMin(buffer_size, length); |
| int l = qMin(buffer_size, length); |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| op.funcSolid(dest, l, data->solid.color, spans->coverage); |
| op.funcSolid(dest, l, data->solid.color, spans->coverage); |
| if (op.dest_store) |
| if (op.dest_store) |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| length -= l; |
| length -= l; |
| x += l; |
| x += l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| static void blend_color_generic_callback(int count, const QSpan *spans, void *userData) |
| static void blend_color_generic_callback(int count, const QSpan *spans, void *userData) |
| { |
| { |
| // ### Falcon |
| // ### Falcon |
| Q_UNUSED(count); |
| Q_UNUSED(count); |
| Q_UNUSED(spans); |
| Q_UNUSED(spans); |
| Q_UNUSED(userData); |
| Q_UNUSED(userData); |
| // QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| // QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| // data->rasterEngine->drawColorSpans(spans, count, data->solid.color); |
| // data->rasterEngine->drawColorSpans(spans, count, data->solid.color); |
| } |
| } |
| #endif // QT_NO_RASTERCALLBACKS |
| #endif // QT_NO_RASTERCALLBACKS |
| |
| |
| static void blend_color_argb(int count, const QSpan *spans, void *userData) |
| static void blend_color_argb(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| if (op.mode == QPainter::CompositionMode_Source) { |
| if (op.mode == QPainter::CompositionMode_Source) { |
| // inline for performance |
| // inline for performance |
| while (count--) { |
| while (count--) { |
| uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| if (spans->coverage == 255) { |
| if (spans->coverage == 255) { |
| QT_MEMFILL_UINT(target, spans->len, data->solid.color); |
| QT_MEMFILL_UINT(target, spans->len, data->solid.color); |
| } else { |
| } else { |
| uint c = BYTE_MUL(data->solid.color, spans->coverage); |
| uint c = BYTE_MUL(data->solid.color, spans->coverage); |
| int ialpha = 255 - spans->coverage; |
| int ialpha = 255 - spans->coverage; |
| for (int i = 0; i < spans->len; ++i) |
| for (int i = 0; i < spans->len; ++i) |
| target[i] = c + BYTE_MUL(target[i], ialpha); |
| target[i] = c + BYTE_MUL(target[i], ialpha); |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| while (count--) { |
| while (count--) { |
| uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| op.funcSolid(target, spans->len, data->solid.color, spans->coverage); |
| op.funcSolid(target, spans->len, data->solid.color, spans->coverage); |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| if (op.mode == QPainter::CompositionMode_Source) { |
| if (op.mode == QPainter::CompositionMode_Source) { |
| const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(data->solid.color), 0); |
| const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(data->solid.color), 0); |
| while (count--) { |
| while (count--) { |
| T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) |
| T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) |
| + spans->x; |
| + spans->x; |
| if (spans->coverage == 255) { |
| if (spans->coverage == 255) { |
| qt_memfill(target, c, spans->len); |
| qt_memfill(target, c, spans->len); |
| } else { |
| } else { |
| const quint8 alpha = T::alpha(spans->coverage); |
| const quint8 alpha = T::alpha(spans->coverage); |
| const T color = c.byte_mul(alpha); |
| const T color = c.byte_mul(alpha); |
| const int ialpha = T::ialpha(spans->coverage); |
| const int ialpha = T::ialpha(spans->coverage); |
| const T *end = target + spans->len; |
| const T *end = target + spans->len; |
| while (target < end) { |
| while (target < end) { |
| *target = color + target->byte_mul(ialpha); |
| *target = color + target->byte_mul(ialpha); |
| ++target; |
| ++target; |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| if (op.mode == QPainter::CompositionMode_SourceOver) { |
| if (op.mode == QPainter::CompositionMode_SourceOver) { |
| while (count--) { |
| while (count--) { |
| const quint32 color = BYTE_MUL(data->solid.color, spans->coverage); |
| const quint32 color = BYTE_MUL(data->solid.color, spans->coverage); |
| const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0); |
| const T c = qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0); |
| const quint8 ialpha = T::alpha(qAlpha(~color)); |
| const quint8 ialpha = T::alpha(qAlpha(~color)); |
| T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| T *target = ((T*)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| const T *end = target + spans->len; |
| const T *end = target + spans->len; |
| while (target != end) { |
| while (target != end) { |
| *target = c + target->byte_mul(ialpha); |
| *target = c + target->byte_mul(ialpha); |
| ++target; |
| ++target; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| blend_color_generic(count, spans, userData); |
| blend_color_generic(count, spans, userData); |
| } |
| } |
| |
| |
| #define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST> |
| #define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST> |
| |
| |
| static void blend_color_rgb16(int count, const QSpan *spans, void *userData) |
| static void blend_color_rgb16(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| /* |
| /* |
| We duplicate a little logic from getOperator() and calculate the |
| We duplicate a little logic from getOperator() and calculate the |
| composition mode directly. This allows blend_color_rgb16 to be used |
| composition mode directly. This allows blend_color_rgb16 to be used |
| from qt_gradient_quint16 with minimal overhead. |
| from qt_gradient_quint16 with minimal overhead. |
| */ |
| */ |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| if (mode == QPainter::CompositionMode_SourceOver && |
| if (mode == QPainter::CompositionMode_SourceOver && |
| qAlpha(data->solid.color) == 255) |
| qAlpha(data->solid.color) == 255) |
| mode = QPainter::CompositionMode_Source; |
| mode = QPainter::CompositionMode_Source; |
| |
| |
| if (mode == QPainter::CompositionMode_Source) { |
| if (mode == QPainter::CompositionMode_Source) { |
| // inline for performance |
| // inline for performance |
| ushort c = qConvertRgb32To16(data->solid.color); |
| ushort c = qConvertRgb32To16(data->solid.color); |
| while (count--) { |
| while (count--) { |
| ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| if (spans->coverage == 255) { |
| if (spans->coverage == 255) { |
| QT_MEMFILL_USHORT(target, spans->len, c); |
| QT_MEMFILL_USHORT(target, spans->len, c); |
| } else { |
| } else { |
| ushort color = BYTE_MUL_RGB16(c, spans->coverage); |
| ushort color = BYTE_MUL_RGB16(c, spans->coverage); |
| int ialpha = 255 - spans->coverage; |
| int ialpha = 255 - spans->coverage; |
| const ushort *end = target + spans->len; |
| const ushort *end = target + spans->len; |
| while (target < end) { |
| while (target < end) { |
| *target = color + BYTE_MUL_RGB16(*target, ialpha); |
| *target = color + BYTE_MUL_RGB16(*target, ialpha); |
| ++target; |
| ++target; |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| if (mode == QPainter::CompositionMode_SourceOver) { |
| if (mode == QPainter::CompositionMode_SourceOver) { |
| while (count--) { |
| while (count--) { |
| uint color = BYTE_MUL(data->solid.color, spans->coverage); |
| uint color = BYTE_MUL(data->solid.color, spans->coverage); |
| int ialpha = qAlpha(~color); |
| int ialpha = qAlpha(~color); |
| ushort c = qConvertRgb32To16(color); |
| ushort c = qConvertRgb32To16(color); |
| ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| ushort *target = ((ushort *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| int len = spans->len; |
| int len = spans->len; |
| bool pre = (((quintptr)target) & 0x3) != 0; |
| bool pre = (((quintptr)target) & 0x3) != 0; |
| bool post = false; |
| bool post = false; |
| if (pre) { |
| if (pre) { |
| // skip to word boundary |
| // skip to word boundary |
| *target = c + BYTE_MUL_RGB16(*target, ialpha); |
| *target = c + BYTE_MUL_RGB16(*target, ialpha); |
| ++target; |
| ++target; |
| --len; |
| --len; |
| } |
| } |
| if (len & 0x1) { |
| if (len & 0x1) { |
| post = true; |
| post = true; |
| --len; |
| --len; |
| } |
| } |
| uint *target32 = (uint*)target; |
| uint *target32 = (uint*)target; |
| uint c32 = c | (c<<16); |
| uint c32 = c | (c<<16); |
| len >>= 1; |
| len >>= 1; |
| uint salpha = (ialpha+1) >> 3; // calculate here rather than in loop |
| uint salpha = (ialpha+1) >> 3; // calculate here rather than in loop |
| while (len--) { |
| while (len--) { |
| // blend full words |
| // blend full words |
| *target32 = c32 + BYTE_MUL_RGB16_32(*target32, salpha); |
| *target32 = c32 + BYTE_MUL_RGB16_32(*target32, salpha); |
| ++target32; |
| ++target32; |
| target += 2; |
| target += 2; |
| } |
| } |
| if (post) { |
| if (post) { |
| // one last pixel beyond a full word |
| // one last pixel beyond a full word |
| *target = c + BYTE_MUL_RGB16(*target, ialpha); |
| *target = c + BYTE_MUL_RGB16(*target, ialpha); |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| blend_color_generic(count, spans, userData); |
| blend_color_generic(count, spans, userData); |
| } |
| } |
| |
| |
| template <typename T> |
| template <typename T> |
| void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler) |
| void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler) |
| { |
| { |
| uint const_alpha = 256; |
| uint const_alpha = 256; |
| if (data->type == QSpanData::Texture) |
| if (data->type == QSpanData::Texture) |
| const_alpha = data->texture.const_alpha; |
| const_alpha = data->texture.const_alpha; |
| |
| |
| int coverage = 0; |
| int coverage = 0; |
| while (count) { |
| while (count) { |
| int x = spans->x; |
| int x = spans->x; |
| const int y = spans->y; |
| const int y = spans->y; |
| int right = x + spans->len; |
| int right = x + spans->len; |
| |
| |
| // compute length of adjacent spans |
| // compute length of adjacent spans |
| for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i) |
| for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i) |
| right += spans[i].len; |
| right += spans[i].len; |
| int length = right - x; |
| int length = right - x; |
| |
| |
| while (length) { |
| while (length) { |
| int l = qMin(buffer_size, length); |
| int l = qMin(buffer_size, length); |
| length -= l; |
| length -= l; |
| |
| |
| int process_length = l; |
| int process_length = l; |
| int process_x = x; |
| int process_x = x; |
| |
| |
| const uint *src = handler.fetch(process_x, y, process_length); |
| const uint *src = handler.fetch(process_x, y, process_length); |
| int offset = 0; |
| int offset = 0; |
| while (l > 0) { |
| while (l > 0) { |
| if (x == spans->x) // new span? |
| if (x == spans->x) // new span? |
| coverage = (spans->coverage * const_alpha) >> 8; |
| coverage = (spans->coverage * const_alpha) >> 8; |
| |
| |
| int right = spans->x + spans->len; |
| int right = spans->x + spans->len; |
| int len = qMin(l, right - x); |
| int len = qMin(l, right - x); |
| |
| |
| handler.process(x, y, len, coverage, src, offset); |
| handler.process(x, y, len, coverage, src, offset); |
| |
| |
| l -= len; |
| l -= len; |
| x += len; |
| x += len; |
| offset += len; |
| offset += len; |
| |
| |
| if (x == right) { // done with current span? |
| if (x == right) { // done with current span? |
| ++spans; |
| ++spans; |
| --count; |
| --count; |
| } |
| } |
| } |
| } |
| handler.store(process_x, y, process_length); |
| handler.store(process_x, y, process_length); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| struct QBlendBase |
| struct QBlendBase |
| { |
| { |
| QBlendBase(QSpanData *d, Operator o) |
| QBlendBase(QSpanData *d, Operator o) |
| : data(d) |
| : data(d) |
| , op(o) |
| , op(o) |
| , dest(0) |
| , dest(0) |
| { |
| { |
| } |
| } |
| |
| |
| QSpanData *data; |
| QSpanData *data; |
| Operator op; |
| Operator op; |
| |
| |
| uint *dest; |
| uint *dest; |
| |
| |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| }; |
| }; |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| class BlendSrcGeneric : public QBlendBase |
| class BlendSrcGeneric : public QBlendBase |
| { |
| { |
| public: |
| public: |
| BlendSrcGeneric(QSpanData *d, Operator o) |
| BlendSrcGeneric(QSpanData *d, Operator o) |
| : QBlendBase(d, o) |
| : QBlendBase(d, o) |
| { |
| { |
| } |
| } |
| |
| |
| const uint *fetch(int x, int y, int len) |
| const uint *fetch(int x, int y, int len) |
| { |
| { |
| if (spanMethod == RegularSpans) |
| 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); |
| 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 x, int y, int len, int coverage, const uint *src, int offset) |
| { |
| { |
| if (spanMethod == RegularSpans) |
| if (spanMethod == RegularSpans) |
| op.func(dest + offset, src + offset, len, coverage); |
| op.func(dest + offset, src + offset, len, coverage); |
| else |
| else |
| drawBufferSpan(data, src + offset, len, x, y, len, coverage); |
| drawBufferSpan(data, src + offset, len, x, y, len, coverage); |
| } |
| } |
| |
| |
| void store(int x, int y, int len) |
| void store(int x, int y, int len) |
| { |
| { |
| if (spanMethod == RegularSpans && op.dest_store) { |
| if (spanMethod == RegularSpans && op.dest_store) { |
| op.dest_store(data->rasterBuffer, x, y, dest, len); |
| op.dest_store(data->rasterBuffer, x, y, dest, len); |
| } |
| } |
| } |
| } |
| }; |
| }; |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count)); |
| BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count)); |
| handleSpans(count, spans, data, blend); |
| handleSpans(count, spans, data, blend); |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx); |
| int xoff = -qRound(-data->dx); |
| int yoff = -qRound(-data->dy); |
| int yoff = -qRound(-data->dy); |
| |
| |
| while (count--) { |
| while (count--) { |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = xoff + x; |
| int sx = xoff + x; |
| int sy = yoff + spans->y; |
| int sy = yoff + spans->y; |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sx < 0) { |
| if (sx < 0) { |
| x -= sx; |
| x -= sx; |
| length += sx; |
| length += sx; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| if (sx + length > image_width) |
| if (sx + length > image_width) |
| length = image_width - sx; |
| length = image_width - sx; |
| if (length > 0) { |
| if (length > 0) { |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| while (length) { |
| while (length) { |
| int l = qMin(buffer_size, length); |
| int l = qMin(buffer_size, length); |
| const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); |
| const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); |
| if (spanMethod == RegularSpans) { |
| if (spanMethod == RegularSpans) { |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| op.func(dest, src, l, coverage); |
| op.func(dest, src, l, coverage); |
| if (op.dest_store) |
| if (op.dest_store) |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| } else { |
| } else { |
| drawBufferSpan(data, src, l, x, spans->y, |
| drawBufferSpan(data, src, l, x, spans->y, |
| l, coverage); |
| l, coverage); |
| } |
| } |
| x += l; |
| x += l; |
| sx += l; |
| sx += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| && data->texture.format != QImage::Format_RGB32) { |
| && data->texture.format != QImage::Format_RGB32) { |
| blend_untransformed_generic<spanMethod>(count, spans, userData); |
| blend_untransformed_generic<spanMethod>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx); |
| int xoff = -qRound(-data->dx); |
| int yoff = -qRound(-data->dy); |
| int yoff = -qRound(-data->dy); |
| |
| |
| while (count--) { |
| while (count--) { |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = xoff + x; |
| int sx = xoff + x; |
| int sy = yoff + spans->y; |
| int sy = yoff + spans->y; |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sx < 0) { |
| if (sx < 0) { |
| x -= sx; |
| x -= sx; |
| length += sx; |
| length += sx; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| if (sx + length > image_width) |
| if (sx + length > image_width) |
| length = image_width - sx; |
| length = image_width - sx; |
| if (length > 0) { |
| if (length > 0) { |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const uint *src = (uint *)data->texture.scanLine(sy) + sx; |
| const uint *src = (uint *)data->texture.scanLine(sy) + sx; |
| if (spanMethod == RegularSpans) { |
| if (spanMethod == RegularSpans) { |
| uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; |
| uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; |
| op.func(dest, src, length, coverage); |
| op.func(dest, src, length, coverage); |
| } else { |
| } else { |
| drawBufferSpan(data, src, length, x, |
| drawBufferSpan(data, src, length, x, |
| spans->y, length, coverage); |
| spans->y, length, coverage); |
| } |
| } |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| static inline quint16 interpolate_pixel_rgb16_255(quint16 x, quint8 a, |
| static inline quint16 interpolate_pixel_rgb16_255(quint16 x, quint8 a, |
| quint16 y, quint8 b) |
| quint16 y, quint8 b) |
| { |
| { |
| quint16 t = ((((x & 0x07e0) * a) + ((y & 0x07e0) * b)) >> 5) & 0x07e0; |
| quint16 t = ((((x & 0x07e0) * a) + ((y & 0x07e0) * b)) >> 5) & 0x07e0; |
| t |= ((((x & 0xf81f) * a) + ((y & 0xf81f) * b)) >> 5) & 0xf81f; |
| t |= ((((x & 0xf81f) * a) + ((y & 0xf81f) * b)) >> 5) & 0xf81f; |
| |
| |
| return t; |
| return t; |
| } |
| } |
| |
| |
| static inline quint32 interpolate_pixel_rgb16x2_255(quint32 x, quint8 a, |
| static inline quint32 interpolate_pixel_rgb16x2_255(quint32 x, quint8 a, |
| quint32 y, quint8 b) |
| quint32 y, quint8 b) |
| { |
| { |
| uint t; |
| uint t; |
| t = ((((x & 0xf81f07e0) >> 5) * a) + (((y & 0xf81f07e0) >> 5) * b)) & 0xf81f07e0; |
| t = ((((x & 0xf81f07e0) >> 5) * a) + (((y & 0xf81f07e0) >> 5) * b)) & 0xf81f07e0; |
| t |= ((((x & 0x07e0f81f) * a) + ((y & 0x07e0f81f) * b)) >> 5) & 0x07e0f81f; |
| t |= ((((x & 0x07e0f81f) * a) + ((y & 0x07e0f81f) * b)) >> 5) & 0x07e0f81f; |
| return t; |
| return t; |
| } |
| } |
| |
| |
| static inline void blend_sourceOver_rgb16_rgb16(quint16 *dest, |
| static inline void blend_sourceOver_rgb16_rgb16(quint16 *dest, |
| const quint16 *src, |
| const quint16 *src, |
| int length, |
| int length, |
| const quint8 alpha, |
| const quint8 alpha, |
| const quint8 ialpha) |
| const quint8 ialpha) |
| { |
| { |
| const int dstAlign = ((quintptr)dest) & 0x3; |
| const int dstAlign = ((quintptr)dest) & 0x3; |
| if (dstAlign) { |
| if (dstAlign) { |
| *dest = interpolate_pixel_rgb16_255(*src, alpha, *dest, ialpha); |
| *dest = interpolate_pixel_rgb16_255(*src, alpha, *dest, ialpha); |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| --length; |
| --length; |
| } |
| } |
| const int srcAlign = ((quintptr)src) & 0x3; |
| const int srcAlign = ((quintptr)src) & 0x3; |
| int length32 = length >> 1; |
| int length32 = length >> 1; |
| if (length32 && srcAlign == 0) { |
| if (length32 && srcAlign == 0) { |
| while (length32--) { |
| while (length32--) { |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| *dest32 = interpolate_pixel_rgb16x2_255(*src32, alpha, |
| *dest32 = interpolate_pixel_rgb16x2_255(*src32, alpha, |
| *dest32, ialpha); |
| *dest32, ialpha); |
| dest += 2; |
| dest += 2; |
| src += 2; |
| src += 2; |
| } |
| } |
| length &= 0x1; |
| length &= 0x1; |
| } |
| } |
| while (length--) { |
| while (length--) { |
| *dest = interpolate_pixel_rgb16_255(*src, alpha, *dest, ialpha); |
| *dest = interpolate_pixel_rgb16_255(*src, alpha, *dest, ialpha); |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline void madd_2(DST *dest, const quint16 alpha, const SRC *src) |
| inline void madd_2(DST *dest, const quint16 alpha, const SRC *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| dest[0] = dest[0].byte_mul(alpha >> 8) + DST(src[0]); |
| dest[0] = dest[0].byte_mul(alpha >> 8) + DST(src[0]); |
| dest[1] = dest[1].byte_mul(alpha & 0xff) + DST(src[1]); |
| dest[1] = dest[1].byte_mul(alpha & 0xff) + DST(src[1]); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline void madd_4(DST *dest, const quint32 alpha, const SRC *src) |
| inline void madd_4(DST *dest, const quint32 alpha, const SRC *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| dest[0] = dest[0].byte_mul(alpha >> 24) + DST(src[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[1] = dest[1].byte_mul((alpha >> 16) & 0xff) + DST(src[1]); |
| dest[2] = dest[2].byte_mul((alpha >> 8) & 0xff) + DST(src[2]); |
| dest[2] = dest[2].byte_mul((alpha >> 8) & 0xff) + DST(src[2]); |
| dest[3] = dest[3].byte_mul(alpha & 0xff) + DST(src[3]); |
| dest[3] = dest[3].byte_mul(alpha & 0xff) + DST(src[3]); |
| } |
| } |
| |
| |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline void madd_4(qargb8565 *dest, const quint32 a, const qargb8565 *src) |
| inline void madd_4(qargb8565 *dest, const quint32 a, const qargb8565 *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 x, y, t; |
| quint32 x, y, t; |
| quint8 a8; |
| quint8 a8; |
| |
| |
| { |
| { |
| x = dest32[0]; |
| x = dest32[0]; |
| y = src32[0]; |
| y = src32[0]; |
| |
| |
| a8 = a >> 24; |
| a8 = a >> 24; |
| |
| |
| // a0,g0 |
| // a0,g0 |
| t = ((((x & 0x0007e0ff) * a8) >> 5) & 0x0007e0ff) + (y & 0x0007c0f8); |
| t = ((((x & 0x0007e0ff) * a8) >> 5) & 0x0007e0ff) + (y & 0x0007c0f8); |
| |
| |
| // r0,b0 |
| // r0,b0 |
| t |= ((((x & 0x00f81f00) * a8) >> 5) & 0x00f81f00) + (y & 0x00f81f00); |
| t |= ((((x & 0x00f81f00) * a8) >> 5) & 0x00f81f00) + (y & 0x00f81f00); |
| |
| |
| a8 = (a >> 16) & 0xff; |
| a8 = (a >> 16) & 0xff; |
| |
| |
| // a1 |
| // a1 |
| t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); |
| t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); |
| |
| |
| dest32[0] = t; |
| dest32[0] = t; |
| } |
| } |
| { |
| { |
| x = dest32[1]; |
| x = dest32[1]; |
| y = src32[1]; |
| y = src32[1]; |
| |
| |
| // r1,b1 |
| // r1,b1 |
| t = ((((x & 0x0000f81f) * a8) >> 5) & 0x0000f81f) + (y & 0x0000f81f); |
| t = ((((x & 0x0000f81f) * a8) >> 5) & 0x0000f81f) + (y & 0x0000f81f); |
| |
| |
| // g1 |
| // g1 |
| t |= ((((x & 0x000007e0) * a8) >> 5) & 0x000007e0) + (y & 0x000007c0); |
| t |= ((((x & 0x000007e0) * a8) >> 5) & 0x000007e0) + (y & 0x000007c0); |
| |
| |
| a8 = (a >> 8) & 0xff; |
| a8 = (a >> 8) & 0xff; |
| |
| |
| // a2 |
| // a2 |
| t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); |
| t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); |
| |
| |
| { |
| { |
| // rgb2 |
| // rgb2 |
| quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 t16; |
| quint16 t16; |
| |
| |
| t16 = ((((x16 & 0xf81f) * a8) >> 5) & 0xf81f) + (y16 & 0xf81f); |
| t16 = ((((x16 & 0xf81f) * a8) >> 5) & 0xf81f) + (y16 & 0xf81f); |
| t16 |= ((((x16 & 0x07e0) * a8) >> 5) & 0x07e0) + (y16 & 0x07c0); |
| t16 |= ((((x16 & 0x07e0) * a8) >> 5) & 0x07e0) + (y16 & 0x07c0); |
| |
| |
| // rg2 |
| // rg2 |
| t |= ((t16 & 0x00ff) << 24); |
| t |= ((t16 & 0x00ff) << 24); |
| |
| |
| dest32[1] = t; |
| dest32[1] = t; |
| |
| |
| x = dest32[2]; |
| x = dest32[2]; |
| y = src32[2]; |
| y = src32[2]; |
| |
| |
| // gb2 |
| // gb2 |
| t = (t16 >> 8); |
| t = (t16 >> 8); |
| } |
| } |
| } |
| } |
| { |
| { |
| a8 = a & 0xff; |
| a8 = a & 0xff; |
| |
| |
| // g3,a3 |
| // g3,a3 |
| t |= ((((x & 0x07e0ff00) * a8) >> 5) & 0x07e0ff00) + (y & 0x07c0f800); |
| t |= ((((x & 0x07e0ff00) * a8) >> 5) & 0x07e0ff00) + (y & 0x07c0f800); |
| |
| |
| // r3,b3 |
| // r3,b3 |
| t |= ((((x & 0xf81f0000) >> 5) * a8) & 0xf81f0000)+ (y & 0xf81f0000); |
| t |= ((((x & 0xf81f0000) >> 5) * a8) & 0xf81f0000)+ (y & 0xf81f0000); |
| |
| |
| dest32[2] = t; |
| dest32[2] = t; |
| } |
| } |
| } |
| } |
| #endif |
| #endif |
| |
| |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline void madd_4(qargb8555 *dest, const quint32 a, const qargb8555 *src) |
| inline void madd_4(qargb8555 *dest, const quint32 a, const qargb8555 *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 x, y, t; |
| quint32 x, y, t; |
| quint8 a8; |
| quint8 a8; |
| |
| |
| { |
| { |
| x = dest32[0]; |
| x = dest32[0]; |
| y = src32[0]; |
| y = src32[0]; |
| |
| |
| a8 = a >> 24; |
| a8 = a >> 24; |
| |
| |
| // a0,g0 |
| // a0,g0 |
| t = ((((x & 0x0003e0ff) * a8) >> 5) & 0x0003e0ff) + (y & 0x0003e0f8); |
| t = ((((x & 0x0003e0ff) * a8) >> 5) & 0x0003e0ff) + (y & 0x0003e0f8); |
| |
| |
| // r0,b0 |
| // r0,b0 |
| t |= ((((x & 0x007c1f00) * a8) >> 5) & 0x007c1f00) + (y & 0x007c1f00); |
| t |= ((((x & 0x007c1f00) * a8) >> 5) & 0x007c1f00) + (y & 0x007c1f00); |
| |
| |
| a8 = (a >> 16) & 0xff; |
| a8 = (a >> 16) & 0xff; |
| |
| |
| // a1 |
| // a1 |
| t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); |
| t |= ((((x & 0xff000000) >> 5) * a8) & 0xff000000) + (y & 0xf8000000); |
| |
| |
| dest32[0] = t; |
| dest32[0] = t; |
| } |
| } |
| { |
| { |
| x = dest32[1]; |
| x = dest32[1]; |
| y = src32[1]; |
| y = src32[1]; |
| |
| |
| // r1,b1 |
| // r1,b1 |
| t = ((((x & 0x00007c1f) * a8) >> 5) & 0x00007c1f) + (y & 0x00007c1f); |
| t = ((((x & 0x00007c1f) * a8) >> 5) & 0x00007c1f) + (y & 0x00007c1f); |
| |
| |
| // g1 |
| // g1 |
| t |= ((((x & 0x000003e0) * a8) >> 5) & 0x000003e0) + (y & 0x000003e0); |
| t |= ((((x & 0x000003e0) * a8) >> 5) & 0x000003e0) + (y & 0x000003e0); |
| |
| |
| a8 = (a >> 8) & 0xff; |
| a8 = (a >> 8) & 0xff; |
| |
| |
| // a2 |
| // a2 |
| t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); |
| t |= ((((x & 0x00ff0000) * a8) >> 5) & 0x00ff0000) + (y & 0x00f80000); |
| |
| |
| { |
| { |
| // rgb2 |
| // rgb2 |
| quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 x16 = (x >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 t16; |
| quint16 t16; |
| |
| |
| t16 = ((((x16 & 0x7c1f) * a8) >> 5) & 0x7c1f) + (y16 & 0x7c1f); |
| t16 = ((((x16 & 0x7c1f) * a8) >> 5) & 0x7c1f) + (y16 & 0x7c1f); |
| t16 |= ((((x16 & 0x03e0) * a8) >> 5) & 0x03e0) + (y16 & 0x03e0); |
| t16 |= ((((x16 & 0x03e0) * a8) >> 5) & 0x03e0) + (y16 & 0x03e0); |
| |
| |
| // rg2 |
| // rg2 |
| t |= ((t16 & 0x00ff) << 24); |
| t |= ((t16 & 0x00ff) << 24); |
| |
| |
| dest32[1] = t; |
| dest32[1] = t; |
| |
| |
| x = dest32[2]; |
| x = dest32[2]; |
| y = src32[2]; |
| y = src32[2]; |
| |
| |
| // gb2 |
| // gb2 |
| t = (t16 >> 8); |
| t = (t16 >> 8); |
| } |
| } |
| } |
| } |
| { |
| { |
| a8 = a & 0xff; |
| a8 = a & 0xff; |
| |
| |
| // g3,a3 |
| // g3,a3 |
| t |= ((((x & 0x03e0ff00) * a8) >> 5) & 0x03e0ff00) + (y & 0x03e0f800); |
| t |= ((((x & 0x03e0ff00) * a8) >> 5) & 0x03e0ff00) + (y & 0x03e0f800); |
| |
| |
| // r3,b3 |
| // r3,b3 |
| t |= ((((x & 0x7c1f0000) >> 5) * a8) & 0x7c1f0000)+ (y & 0x7c1f0000); |
| t |= ((((x & 0x7c1f0000) >> 5) * a8) & 0x7c1f0000)+ (y & 0x7c1f0000); |
| |
| |
| dest32[2] = t; |
| dest32[2] = t; |
| } |
| } |
| } |
| } |
| #endif |
| #endif |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 alpha_2(const T *src) |
| inline quint16 alpha_2(const T *src) |
| { |
| { |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| if (T::hasAlpha()) |
| if (T::hasAlpha()) |
| return (src[0].alpha() << 8) | src[1].alpha(); |
| return (src[0].alpha() << 8) | src[1].alpha(); |
| else |
| else |
| return 0xffff; |
| return 0xffff; |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 alpha_4(const T *src) |
| inline quint32 alpha_4(const T *src) |
| { |
| { |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| if (T::hasAlpha()) { |
| if (T::hasAlpha()) { |
| return (src[0].alpha() << 24) | (src[1].alpha() << 16) |
| return (src[0].alpha() << 24) | (src[1].alpha() << 16) |
| | (src[2].alpha() << 8) | src[3].alpha(); |
| | (src[2].alpha() << 8) | src[3].alpha(); |
| } else { |
| } else { |
| return 0xffffffff; |
| return 0xffffffff; |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 alpha_4(const qargb8565 *src) |
| inline quint32 alpha_4(const qargb8565 *src) |
| { |
| { |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; |
| return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 alpha_4(const qargb6666 *src) |
| inline quint32 alpha_4(const qargb6666 *src) |
| { |
| { |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| return ((src8[2] & 0xfc) | (src8[2] >> 6)) << 24 |
| return ((src8[2] & 0xfc) | (src8[2] >> 6)) << 24 |
| | ((src8[5] & 0xfc) | (src8[5] >> 6)) << 16 |
| | ((src8[5] & 0xfc) | (src8[5] >> 6)) << 16 |
| | ((src8[8] & 0xfc) | (src8[8] >> 6)) << 8 |
| | ((src8[8] & 0xfc) | (src8[8] >> 6)) << 8 |
| | ((src8[11] & 0xfc) | (src8[11] >> 6)); |
| | ((src8[11] & 0xfc) | (src8[11] >> 6)); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 alpha_4(const qargb8555 *src) |
| inline quint32 alpha_4(const qargb8555 *src) |
| { |
| { |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| const quint8 *src8 = reinterpret_cast<const quint8*>(src); |
| return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; |
| return src8[0] << 24 | src8[3] << 16 | src8[6] << 8 | src8[9]; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 alpha_2(const qargb4444 *src) |
| inline quint16 alpha_2(const qargb4444 *src) |
| { |
| { |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 t = (*src32 & 0xf000f000) | |
| const quint32 t = (*src32 & 0xf000f000) | |
| ((*src32 & 0xf000f000) >> 4); |
| ((*src32 & 0xf000f000) >> 4); |
| return (t >> 24) | (t & 0xff00); |
| return (t >> 24) | (t & 0xff00); |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_alpha_2(quint16 alpha, const T*) |
| inline quint16 eff_alpha_2(quint16 alpha, const T*) |
| { |
| { |
| return (T::alpha((alpha >> 8) & 0xff) << 8) |
| return (T::alpha((alpha >> 8) & 0xff) << 8) |
| | T::alpha(alpha & 0xff); |
| | T::alpha(alpha & 0xff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_alpha_2(quint16 a, const qrgb565*) |
| inline quint16 eff_alpha_2(quint16 a, const qrgb565*) |
| { |
| { |
| return ((((a & 0xff00) + 0x0100) >> 3) & 0xff00) |
| return ((((a & 0xff00) + 0x0100) >> 3) & 0xff00) |
| | ((((a & 0x00ff) + 0x0001) >> 3) & 0x00ff); |
| | ((((a & 0x00ff) + 0x0001) >> 3) & 0x00ff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_alpha_2(quint16 a, const qrgb444*) |
| inline quint16 eff_alpha_2(quint16 a, const qrgb444*) |
| { |
| { |
| return (((a & 0x00ff) + 0x0001) >> 4) |
| return (((a & 0x00ff) + 0x0001) >> 4) |
| | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); |
| | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_alpha_2(quint16 a, const qargb4444*) |
| inline quint16 eff_alpha_2(quint16 a, const qargb4444*) |
| { |
| { |
| return (((a & 0x00ff) + 0x0001) >> 4) |
| return (((a & 0x00ff) + 0x0001) >> 4) |
| | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); |
| | ((((a & 0xff00) + 0x0100) >> 4) & 0xff00); |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_ialpha_2(quint16 alpha, const T*) |
| inline quint16 eff_ialpha_2(quint16 alpha, const T*) |
| { |
| { |
| return (T::ialpha((alpha >> 8) & 0xff) << 8) |
| return (T::ialpha((alpha >> 8) & 0xff) << 8) |
| | T::ialpha(alpha & 0xff); |
| | T::ialpha(alpha & 0xff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_ialpha_2(quint16 a, const qrgb565 *dummy) |
| inline quint16 eff_ialpha_2(quint16 a, const qrgb565 *dummy) |
| { |
| { |
| return 0x2020 - eff_alpha_2(a, dummy); |
| return 0x2020 - eff_alpha_2(a, dummy); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_ialpha_2(quint16 a, const qargb4444 *dummy) |
| inline quint16 eff_ialpha_2(quint16 a, const qargb4444 *dummy) |
| { |
| { |
| return 0x1010 - eff_alpha_2(a, dummy); |
| return 0x1010 - eff_alpha_2(a, dummy); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint16 eff_ialpha_2(quint16 a, const qrgb444 *dummy) |
| inline quint16 eff_ialpha_2(quint16 a, const qrgb444 *dummy) |
| { |
| { |
| return 0x1010 - eff_alpha_2(a, dummy); |
| return 0x1010 - eff_alpha_2(a, dummy); |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 alpha, const T*) |
| inline quint32 eff_alpha_4(quint32 alpha, const T*) |
| { |
| { |
| return (T::alpha(alpha >> 24) << 24) |
| return (T::alpha(alpha >> 24) << 24) |
| | (T::alpha((alpha >> 16) & 0xff) << 16) |
| | (T::alpha((alpha >> 16) & 0xff) << 16) |
| | (T::alpha((alpha >> 8) & 0xff) << 8) |
| | (T::alpha((alpha >> 8) & 0xff) << 8) |
| | T::alpha(alpha & 0xff); |
| | T::alpha(alpha & 0xff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 a, const qrgb888*) |
| inline quint32 eff_alpha_4(quint32 a, const qrgb888*) |
| { |
| { |
| return a; |
| return a; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 a, const qargb8565*) |
| inline quint32 eff_alpha_4(quint32 a, const qargb8565*) |
| { |
| { |
| return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) |
| return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 a, const qargb6666*) |
| inline quint32 eff_alpha_4(quint32 a, const qargb6666*) |
| { |
| { |
| return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) |
| return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 a, const qrgb666*) |
| inline quint32 eff_alpha_4(quint32 a, const qrgb666*) |
| { |
| { |
| return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) |
| return ((((a & 0xff00ff00) >> 2) + 0x00400040) & 0xff00ff00) |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 2) & 0x00ff00ff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_alpha_4(quint32 a, const qargb8555*) |
| inline quint32 eff_alpha_4(quint32 a, const qargb8555*) |
| { |
| { |
| return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) |
| return ((((a & 0xff00ff00) + 0x01000100) >> 3) & 0xff00ff00) |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); |
| | ((((a & 0x00ff00ff) + 0x00010001) >> 3) & 0x00ff00ff); |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 alpha, const T*) |
| inline quint32 eff_ialpha_4(quint32 alpha, const T*) |
| { |
| { |
| return (T::ialpha(alpha >> 24) << 24) |
| return (T::ialpha(alpha >> 24) << 24) |
| | (T::ialpha((alpha >> 16) & 0xff) << 16) |
| | (T::ialpha((alpha >> 16) & 0xff) << 16) |
| | (T::ialpha((alpha >> 8) & 0xff) << 8) |
| | (T::ialpha((alpha >> 8) & 0xff) << 8) |
| | T::ialpha(alpha & 0xff); |
| | T::ialpha(alpha & 0xff); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 a, const qrgb888*) |
| inline quint32 eff_ialpha_4(quint32 a, const qrgb888*) |
| { |
| { |
| return ~a; |
| return ~a; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 a, const qargb8565 *dummy) |
| inline quint32 eff_ialpha_4(quint32 a, const qargb8565 *dummy) |
| { |
| { |
| return 0x20202020 - eff_alpha_4(a, dummy); |
| return 0x20202020 - eff_alpha_4(a, dummy); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 a, const qargb6666 *dummy) |
| inline quint32 eff_ialpha_4(quint32 a, const qargb6666 *dummy) |
| { |
| { |
| return 0x40404040 - eff_alpha_4(a, dummy); |
| return 0x40404040 - eff_alpha_4(a, dummy); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 a, const qrgb666 *dummy) |
| inline quint32 eff_ialpha_4(quint32 a, const qrgb666 *dummy) |
| { |
| { |
| return 0x40404040 - eff_alpha_4(a, dummy); |
| return 0x40404040 - eff_alpha_4(a, dummy); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| inline quint32 eff_ialpha_4(quint32 a, const qargb8555 *dummy) |
| inline quint32 eff_ialpha_4(quint32 a, const qargb8555 *dummy) |
| { |
| { |
| return 0x20202020 - eff_alpha_4(a, dummy); |
| return 0x20202020 - eff_alpha_4(a, dummy); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel_unaligned_2(DST *dest, const SRC *src, |
| inline void interpolate_pixel_unaligned_2(DST *dest, const SRC *src, |
| quint16 alpha) |
| quint16 alpha) |
| { |
| { |
| const quint16 a = eff_alpha_2(alpha, dest); |
| const quint16 a = eff_alpha_2(alpha, dest); |
| const quint16 ia = eff_ialpha_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[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); |
| dest[1] = DST(src[1]).byte_mul(a & 0xff) + dest[1].byte_mul(ia & 0xff); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha) |
| inline void interpolate_pixel_2(DST *dest, const SRC *src, quint16 alpha) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint16 a = eff_alpha_2(alpha, dest); |
| const quint16 a = eff_alpha_2(alpha, dest); |
| const quint16 ia = eff_ialpha_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[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); |
| dest[1] = DST(src[1]).byte_mul(a & 0xff) + dest[1].byte_mul(ia & 0xff); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel(DST &dest, quint8 a, const SRC &src, quint8 b) |
| inline void interpolate_pixel(DST &dest, quint8 a, const SRC &src, quint8 b) |
| { |
| { |
| if (SRC::hasAlpha() && !DST::hasAlpha()) |
| if (SRC::hasAlpha() && !DST::hasAlpha()) |
| interpolate_pixel(dest, a, DST(src), b); |
| interpolate_pixel(dest, a, DST(src), b); |
| else |
| else |
| dest = dest.byte_mul(a) + DST(src).byte_mul(b); |
| dest = dest.byte_mul(a) + DST(src).byte_mul(b); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel(qargb8565 &dest, quint8 a, |
| inline void interpolate_pixel(qargb8565 &dest, quint8 a, |
| const qargb8565 &src, quint8 b) |
| const qargb8565 &src, quint8 b) |
| { |
| { |
| quint8 *d = reinterpret_cast<quint8*>(&dest); |
| quint8 *d = reinterpret_cast<quint8*>(&dest); |
| const quint8 *s = reinterpret_cast<const quint8*>(&src); |
| const quint8 *s = reinterpret_cast<const quint8*>(&src); |
| d[0] = (d[0] * a + s[0] * b) >> 5; |
| d[0] = (d[0] * a + s[0] * b) >> 5; |
| |
| |
| const quint16 x = (d[2] << 8) | d[1]; |
| const quint16 x = (d[2] << 8) | d[1]; |
| const quint16 y = (s[2] << 8) | s[1]; |
| const quint16 y = (s[2] << 8) | s[1]; |
| quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; |
| quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; |
| t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; |
| t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; |
| |
| |
| d[1] = t & 0xff; |
| d[1] = t & 0xff; |
| d[2] = t >> 8; |
| d[2] = t >> 8; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel(qrgb565 &dest, quint8 a, |
| inline void interpolate_pixel(qrgb565 &dest, quint8 a, |
| const qrgb565 &src, quint8 b) |
| const qrgb565 &src, quint8 b) |
| { |
| { |
| const quint16 x = dest.rawValue(); |
| const quint16 x = dest.rawValue(); |
| const quint16 y = src.rawValue(); |
| const quint16 y = src.rawValue(); |
| quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; |
| quint16 t = (((x & 0x07e0) * a + (y & 0x07e0) * b) >> 5) & 0x07e0; |
| t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; |
| t |= (((x & 0xf81f) * a + (y & 0xf81f) * b) >> 5) & 0xf81f; |
| dest = t; |
| dest = t; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel(qrgb555 &dest, quint8 a, |
| inline void interpolate_pixel(qrgb555 &dest, quint8 a, |
| const qrgb555 &src, quint8 b) |
| const qrgb555 &src, quint8 b) |
| { |
| { |
| const quint16 x = dest.rawValue(); |
| const quint16 x = dest.rawValue(); |
| const quint16 y = src.rawValue(); |
| const quint16 y = src.rawValue(); |
| quint16 t = (((x & 0x03e0) * a + (y & 0x03e0) * b) >> 5) & 0x03e0; |
| quint16 t = (((x & 0x03e0) * a + (y & 0x03e0) * b) >> 5) & 0x03e0; |
| t |= ((((x & 0x7c1f) * a) + ((y & 0x7c1f) * b)) >> 5) & 0x7c1f; |
| t |= ((((x & 0x7c1f) * a) + ((y & 0x7c1f) * b)) >> 5) & 0x7c1f; |
| dest = t; |
| dest = t; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel(qrgb444 &dest, quint8 a, |
| inline void interpolate_pixel(qrgb444 &dest, quint8 a, |
| const qrgb444 &src, quint8 b) |
| const qrgb444 &src, quint8 b) |
| { |
| { |
| const quint16 x = dest.rawValue(); |
| const quint16 x = dest.rawValue(); |
| const quint16 y = src.rawValue(); |
| const quint16 y = src.rawValue(); |
| quint16 t = ((x & 0x00f0) * a + (y & 0x00f0) * b) & 0x0f00; |
| quint16 t = ((x & 0x00f0) * a + (y & 0x00f0) * b) & 0x0f00; |
| t |= ((x & 0x0f0f) * a + (y & 0x0f0f) * b) & 0xf0f0; |
| t |= ((x & 0x0f0f) * a + (y & 0x0f0f) * b) & 0xf0f0; |
| quint16 *d = reinterpret_cast<quint16*>(&dest); |
| quint16 *d = reinterpret_cast<quint16*>(&dest); |
| *d = (t >> 4); |
| *d = (t >> 4); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel_2(DST *dest, quint8 a, |
| inline void interpolate_pixel_2(DST *dest, quint8 a, |
| const SRC *src, quint8 b) |
| const SRC *src, quint8 b) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| Q_ASSERT(!SRC::hasAlpha()); |
| Q_ASSERT(!SRC::hasAlpha()); |
| |
| |
| dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b); |
| 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[1] = dest[1].byte_mul(a) + DST(src[1]).byte_mul(b); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel_2(qrgb565 *dest, quint8 a, |
| inline void interpolate_pixel_2(qrgb565 *dest, quint8 a, |
| const qrgb565 *src, quint8 b) |
| const qrgb565 *src, quint8 b) |
| { |
| { |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| quint32 t = (((*x & 0xf81f07e0) >> 5) * a + |
| quint32 t = (((*x & 0xf81f07e0) >> 5) * a + |
| ((*y & 0xf81f07e0) >> 5) * b) & 0xf81f07e0; |
| ((*y & 0xf81f07e0) >> 5) * b) & 0xf81f07e0; |
| t |= (((*x & 0x07e0f81f) * a |
| t |= (((*x & 0x07e0f81f) * a |
| + (*y & 0x07e0f81f) * b) >> 5) & 0x07e0f81f; |
| + (*y & 0x07e0f81f) * b) >> 5) & 0x07e0f81f; |
| *x = t; |
| *x = t; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel_2(qrgb555 *dest, quint8 a, |
| inline void interpolate_pixel_2(qrgb555 *dest, quint8 a, |
| const qrgb555 *src, quint8 b) |
| const qrgb555 *src, quint8 b) |
| { |
| { |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| quint32 t = (((*x & 0x7c1f03e0) >> 5) * a + |
| quint32 t = (((*x & 0x7c1f03e0) >> 5) * a + |
| ((*y & 0x7c1f03e0) >> 5) * b) & 0x7c1f03e0; |
| ((*y & 0x7c1f03e0) >> 5) * b) & 0x7c1f03e0; |
| t |= (((*x & 0x03e07c1f) * a |
| t |= (((*x & 0x03e07c1f) * a |
| + (*y & 0x03e07c1f) * b) >> 5) & 0x03e07c1f; |
| + (*y & 0x03e07c1f) * b) >> 5) & 0x03e07c1f; |
| *x = t; |
| *x = t; |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel_2(qrgb444 *dest, quint8 a, |
| inline void interpolate_pixel_2(qrgb444 *dest, quint8 a, |
| const qrgb444 *src, quint8 b) |
| const qrgb444 *src, quint8 b) |
| { |
| { |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| quint32 *x = reinterpret_cast<quint32*>(dest); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| const quint32 *y = reinterpret_cast<const quint32*>(src); |
| quint32 t = ((*x & 0x0f0f0f0f) * a + (*y & 0x0f0f0f0f) * b) & 0xf0f0f0f0; |
| quint32 t = ((*x & 0x0f0f0f0f) * a + (*y & 0x0f0f0f0f) * b) & 0xf0f0f0f0; |
| t |= ((*x & 0x00f000f0) * a + (*y & 0x00f000f0) * b) & 0x0f000f00; |
| t |= ((*x & 0x00f000f0) * a + (*y & 0x00f000f0) * b) & 0x0f000f00; |
| *x = t >> 4; |
| *x = t >> 4; |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha) |
| inline void interpolate_pixel_4(DST *dest, const SRC *src, quint32 alpha) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| dest[0] = DST(src[0]).byte_mul(a >> 24) |
| dest[0] = DST(src[0]).byte_mul(a >> 24) |
| + dest[0].byte_mul(ia >> 24); |
| + dest[0].byte_mul(ia >> 24); |
| dest[1] = DST(src[1]).byte_mul((a >> 16) & 0xff) |
| dest[1] = DST(src[1]).byte_mul((a >> 16) & 0xff) |
| + dest[1].byte_mul((ia >> 16) & 0xff); |
| + dest[1].byte_mul((ia >> 16) & 0xff); |
| dest[2] = DST(src[2]).byte_mul((a >> 8) & 0xff) |
| dest[2] = DST(src[2]).byte_mul((a >> 8) & 0xff) |
| + dest[2].byte_mul((ia >> 8) & 0xff); |
| + dest[2].byte_mul((ia >> 8) & 0xff); |
| dest[3] = DST(src[3]).byte_mul(a & 0xff) |
| dest[3] = DST(src[3]).byte_mul(a & 0xff) |
| + dest[3].byte_mul(ia & 0xff); |
| + dest[3].byte_mul(ia & 0xff); |
| } |
| } |
| |
| |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| template <> |
| template <> |
| inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src, |
| inline void interpolate_pixel_4(qargb8565 *dest, const qargb8565 *src, |
| quint32 alpha) |
| quint32 alpha) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| |
| |
| quint32 x, y, t; |
| quint32 x, y, t; |
| quint8 a8, ia8; |
| quint8 a8, ia8; |
| { |
| { |
| x = src32[0]; |
| x = src32[0]; |
| y = dest32[0]; |
| y = dest32[0]; |
| |
| |
| a8 = a >> 24; |
| a8 = a >> 24; |
| ia8 = ia >> 24; |
| ia8 = ia >> 24; |
| |
| |
| // a0,g0 |
| // a0,g0 |
| t = (((x & 0x0007e0ff) * a8 + (y & 0x0007e0ff) * ia8) >> 5) |
| t = (((x & 0x0007e0ff) * a8 + (y & 0x0007e0ff) * ia8) >> 5) |
| & 0x0007e0ff; |
| & 0x0007e0ff; |
| |
| |
| // r0,b0 |
| // r0,b0 |
| t |= (((x & 0x00f81f00) * a8 + (y & 0x00f81f00) * ia8) >> 5) |
| t |= (((x & 0x00f81f00) * a8 + (y & 0x00f81f00) * ia8) >> 5) |
| & 0x00f81f00; |
| & 0x00f81f00; |
| |
| |
| a8 = (a >> 16) & 0xff; |
| a8 = (a >> 16) & 0xff; |
| ia8 = (ia >> 16) & 0xff; |
| ia8 = (ia >> 16) & 0xff; |
| |
| |
| // a1 |
| // a1 |
| t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) |
| t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) |
| & 0xff000000; |
| & 0xff000000; |
| |
| |
| dest32[0] = t; |
| dest32[0] = t; |
| } |
| } |
| { |
| { |
| x = src32[1]; |
| x = src32[1]; |
| y = dest32[1]; |
| y = dest32[1]; |
| |
| |
| // r1,b1 |
| // r1,b1 |
| t = (((x & 0x0000f81f) * a8 + (y & 0x0000f81f) * ia8) >> 5) |
| t = (((x & 0x0000f81f) * a8 + (y & 0x0000f81f) * ia8) >> 5) |
| & 0x0000f81f; |
| & 0x0000f81f; |
| |
| |
| // g1 |
| // g1 |
| t |= (((x & 0x000007e0) * a8 + (y & 0x000007e0) * ia8) >> 5) |
| t |= (((x & 0x000007e0) * a8 + (y & 0x000007e0) * ia8) >> 5) |
| & 0x000007e0; |
| & 0x000007e0; |
| |
| |
| a8 = (a >> 8) & 0xff; |
| a8 = (a >> 8) & 0xff; |
| ia8 = (ia >> 8) & 0xff; |
| ia8 = (ia >> 8) & 0xff; |
| |
| |
| // a2 |
| // a2 |
| t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) |
| t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) |
| & 0x00ff0000; |
| & 0x00ff0000; |
| |
| |
| { |
| { |
| // rgb2 |
| // rgb2 |
| quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 t16; |
| quint16 t16; |
| |
| |
| t16 = (((x16 & 0xf81f) * a8 + (y16 & 0xf81f) * ia8) >> 5) & 0xf81f; |
| t16 = (((x16 & 0xf81f) * a8 + (y16 & 0xf81f) * ia8) >> 5) & 0xf81f; |
| t16 |= (((x16 & 0x07e0) * a8 + (y16 & 0x07e0) * ia8) >> 5) & 0x07e0; |
| t16 |= (((x16 & 0x07e0) * a8 + (y16 & 0x07e0) * ia8) >> 5) & 0x07e0; |
| |
| |
| // rg2 |
| // rg2 |
| t |= ((t16 & 0x00ff) << 24); |
| t |= ((t16 & 0x00ff) << 24); |
| |
| |
| dest32[1] = t; |
| dest32[1] = t; |
| |
| |
| x = src32[2]; |
| x = src32[2]; |
| y = dest32[2]; |
| y = dest32[2]; |
| |
| |
| // gb2 |
| // gb2 |
| t = (t16 >> 8); |
| t = (t16 >> 8); |
| } |
| } |
| } |
| } |
| { |
| { |
| a8 = a & 0xff; |
| a8 = a & 0xff; |
| ia8 = ia & 0xff; |
| ia8 = ia & 0xff; |
| |
| |
| // g3,a3 |
| // g3,a3 |
| t |= (((x & 0x07e0ff00) * a8 + (y & 0x07e0ff00) * ia8) >> 5) |
| t |= (((x & 0x07e0ff00) * a8 + (y & 0x07e0ff00) * ia8) >> 5) |
| & 0x07e0ff00; |
| & 0x07e0ff00; |
| |
| |
| // r3,b3 |
| // r3,b3 |
| t |= (((x & 0xf81f0000) >> 5) * a8 + ((y & 0xf81f0000) >> 5) * ia8) |
| t |= (((x & 0xf81f0000) >> 5) * a8 + ((y & 0xf81f0000) >> 5) * ia8) |
| & 0xf81f0000; |
| & 0xf81f0000; |
| |
| |
| dest32[2] = t; |
| dest32[2] = t; |
| } |
| } |
| } |
| } |
| #endif |
| #endif |
| |
| |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN |
| template <> |
| template <> |
| inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src, |
| inline void interpolate_pixel_4(qargb8555 *dest, const qargb8555 *src, |
| quint32 alpha) |
| quint32 alpha) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| |
| |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| |
| |
| quint32 x, y, t; |
| quint32 x, y, t; |
| quint8 a8, ia8; |
| quint8 a8, ia8; |
| { |
| { |
| x = src32[0]; |
| x = src32[0]; |
| y = dest32[0]; |
| y = dest32[0]; |
| |
| |
| a8 = a >> 24; |
| a8 = a >> 24; |
| ia8 = ia >> 24; |
| ia8 = ia >> 24; |
| |
| |
| // a0,g0 |
| // a0,g0 |
| t = (((x & 0x0003e0ff) * a8 + (y & 0x0003e0ff) * ia8) >> 5) |
| t = (((x & 0x0003e0ff) * a8 + (y & 0x0003e0ff) * ia8) >> 5) |
| & 0x0003e0ff; |
| & 0x0003e0ff; |
| |
| |
| // r0,b0 |
| // r0,b0 |
| t |= (((x & 0x007c1f00) * a8 + (y & 0x007c1f00) * ia8) >> 5) |
| t |= (((x & 0x007c1f00) * a8 + (y & 0x007c1f00) * ia8) >> 5) |
| & 0x007c1f00; |
| & 0x007c1f00; |
| |
| |
| a8 = (a >> 16) & 0xff; |
| a8 = (a >> 16) & 0xff; |
| ia8 = (ia >> 16) & 0xff; |
| ia8 = (ia >> 16) & 0xff; |
| |
| |
| // a1 |
| // a1 |
| t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) |
| t |= (((x & 0xff000000) >> 5) * a8 + ((y & 0xff000000) >> 5) * ia8) |
| & 0xff000000; |
| & 0xff000000; |
| |
| |
| dest32[0] = t; |
| dest32[0] = t; |
| } |
| } |
| { |
| { |
| x = src32[1]; |
| x = src32[1]; |
| y = dest32[1]; |
| y = dest32[1]; |
| |
| |
| // r1,b1 |
| // r1,b1 |
| t = (((x & 0x00007c1f) * a8 + (y & 0x00007c1f) * ia8) >> 5) |
| t = (((x & 0x00007c1f) * a8 + (y & 0x00007c1f) * ia8) >> 5) |
| & 0x00007c1f; |
| & 0x00007c1f; |
| |
| |
| // g1 |
| // g1 |
| t |= (((x & 0x000003e0) * a8 + (y & 0x000003e0) * ia8) >> 5) |
| t |= (((x & 0x000003e0) * a8 + (y & 0x000003e0) * ia8) >> 5) |
| & 0x000003e0; |
| & 0x000003e0; |
| |
| |
| a8 = (a >> 8) & 0xff; |
| a8 = (a >> 8) & 0xff; |
| ia8 = (ia >> 8) & 0xff; |
| ia8 = (ia >> 8) & 0xff; |
| |
| |
| // a2 |
| // a2 |
| t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) |
| t |= (((x & 0x00ff0000) * a8 + (y & 0x00ff0000) * ia8) >> 5) |
| & 0x00ff0000; |
| & 0x00ff0000; |
| |
| |
| { |
| { |
| // rgb2 |
| // rgb2 |
| quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 x16 = (x >> 24) | ((src32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 y16 = (y >> 24) | ((dest32[2] & 0x000000ff) << 8); |
| quint16 t16; |
| quint16 t16; |
| |
| |
| t16 = (((x16 & 0x7c1f) * a8 + (y16 & 0x7c1f) * ia8) >> 5) & 0x7c1f; |
| t16 = (((x16 & 0x7c1f) * a8 + (y16 & 0x7c1f) * ia8) >> 5) & 0x7c1f; |
| t16 |= (((x16 & 0x03e0) * a8 + (y16 & 0x03e0) * ia8) >> 5) & 0x03e0; |
| t16 |= (((x16 & 0x03e0) * a8 + (y16 & 0x03e0) * ia8) >> 5) & 0x03e0; |
| |
| |
| // rg2 |
| // rg2 |
| t |= ((t16 & 0x00ff) << 24); |
| t |= ((t16 & 0x00ff) << 24); |
| |
| |
| dest32[1] = t; |
| dest32[1] = t; |
| |
| |
| x = src32[2]; |
| x = src32[2]; |
| y = dest32[2]; |
| y = dest32[2]; |
| |
| |
| // gb2 |
| // gb2 |
| t = (t16 >> 8); |
| t = (t16 >> 8); |
| } |
| } |
| } |
| } |
| { |
| { |
| a8 = a & 0xff; |
| a8 = a & 0xff; |
| ia8 = ia & 0xff; |
| ia8 = ia & 0xff; |
| |
| |
| // g3,a3 |
| // g3,a3 |
| t |= (((x & 0x03e0ff00) * a8 + (y & 0x03e0ff00) * ia8) >> 5) |
| t |= (((x & 0x03e0ff00) * a8 + (y & 0x03e0ff00) * ia8) >> 5) |
| & 0x03e0ff00; |
| & 0x03e0ff00; |
| |
| |
| // r3,b3 |
| // r3,b3 |
| t |= (((x & 0x7c1f0000) >> 5) * a8 + ((y & 0x7c1f0000) >> 5) * ia8) |
| t |= (((x & 0x7c1f0000) >> 5) * a8 + ((y & 0x7c1f0000) >> 5) * ia8) |
| & 0x7c1f0000; |
| & 0x7c1f0000; |
| |
| |
| dest32[2] = t; |
| dest32[2] = t; |
| } |
| } |
| } |
| } |
| #endif |
| #endif |
| |
| |
| template <> |
| template <> |
| inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src, |
| inline void interpolate_pixel_4(qrgb888 *dest, const qrgb888 *src, |
| quint32 alpha) |
| quint32 alpha) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 a = eff_alpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 ia = eff_ialpha_4(alpha, dest); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| const quint32 *src32 = reinterpret_cast<const quint32*>(src); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| quint32 *dest32 = reinterpret_cast<quint32*>(dest); |
| |
| |
| { |
| { |
| quint32 x = src32[0]; |
| quint32 x = src32[0]; |
| quint32 y = dest32[0]; |
| quint32 y = dest32[0]; |
| |
| |
| quint32 t; |
| quint32 t; |
| t = ((x >> 8) & 0xff00ff) * (a >> 24) |
| t = ((x >> 8) & 0xff00ff) * (a >> 24) |
| + ((y >> 8) & 0xff00ff) * (ia >> 24); |
| + ((y >> 8) & 0xff00ff) * (ia >> 24); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t &= 0xff00ff00; |
| t &= 0xff00ff00; |
| |
| |
| x = (x & 0xff0000) * (a >> 24) |
| x = (x & 0xff0000) * (a >> 24) |
| + (x & 0x0000ff) * ((a >> 16) & 0xff) |
| + (x & 0x0000ff) * ((a >> 16) & 0xff) |
| + (y & 0xff0000) * (ia >> 24) |
| + (y & 0xff0000) * (ia >> 24) |
| + (y & 0x0000ff) * ((ia >> 16) & 0xff); |
| + (y & 0x0000ff) * ((ia >> 16) & 0xff); |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x &= 0x00ff00ff; |
| x &= 0x00ff00ff; |
| |
| |
| dest32[0] = x | t; |
| dest32[0] = x | t; |
| } |
| } |
| { |
| { |
| quint32 x = src32[1]; |
| quint32 x = src32[1]; |
| quint32 y = dest32[1]; |
| quint32 y = dest32[1]; |
| |
| |
| quint32 t; |
| quint32 t; |
| t = ((x >> 8) & 0xff0000) * ((a >> 16) & 0xff) |
| t = ((x >> 8) & 0xff0000) * ((a >> 16) & 0xff) |
| + ((x >> 8) & 0x0000ff) * ((a >> 8) & 0xff) |
| + ((x >> 8) & 0x0000ff) * ((a >> 8) & 0xff) |
| + ((y >> 8) & 0xff0000) * ((ia >> 16) & 0xff) |
| + ((y >> 8) & 0xff0000) * ((ia >> 16) & 0xff) |
| + ((y >> 8) & 0x0000ff) * ((ia >> 8) & 0xff); |
| + ((y >> 8) & 0x0000ff) * ((ia >> 8) & 0xff); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t &= 0xff00ff00; |
| t &= 0xff00ff00; |
| |
| |
| x = (x & 0xff0000) * ((a >> 16) & 0xff) |
| x = (x & 0xff0000) * ((a >> 16) & 0xff) |
| + (x & 0x0000ff) * ((a >> 8) & 0xff) |
| + (x & 0x0000ff) * ((a >> 8) & 0xff) |
| + (y & 0xff0000) * ((ia >> 16) & 0xff) |
| + (y & 0xff0000) * ((ia >> 16) & 0xff) |
| + (y & 0x0000ff) * ((ia >> 8) & 0xff); |
| + (y & 0x0000ff) * ((ia >> 8) & 0xff); |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x &= 0x00ff00ff; |
| x &= 0x00ff00ff; |
| |
| |
| dest32[1] = x | t; |
| dest32[1] = x | t; |
| } |
| } |
| { |
| { |
| quint32 x = src32[2]; |
| quint32 x = src32[2]; |
| quint32 y = dest32[2]; |
| quint32 y = dest32[2]; |
| |
| |
| quint32 t; |
| quint32 t; |
| t = ((x >> 8) & 0xff0000) * ((a >> 8) & 0xff) |
| t = ((x >> 8) & 0xff0000) * ((a >> 8) & 0xff) |
| + ((x >> 8) & 0x0000ff) * (a & 0xff) |
| + ((x >> 8) & 0x0000ff) * (a & 0xff) |
| + ((y >> 8) & 0xff0000) * ((ia >> 8) & 0xff) |
| + ((y >> 8) & 0xff0000) * ((ia >> 8) & 0xff) |
| + ((y >> 8) & 0x0000ff) * (ia & 0xff); |
| + ((y >> 8) & 0x0000ff) * (ia & 0xff); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t = (t + ((t >> 8) & 0xff00ff) + 0x800080); |
| t &= 0xff00ff00; |
| t &= 0xff00ff00; |
| |
| |
| x = (x & 0xff00ff) * (a & 0xff) |
| x = (x & 0xff00ff) * (a & 0xff) |
| + (y & 0xff00ff) * (ia & 0xff); |
| + (y & 0xff00ff) * (ia & 0xff); |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x = (x + ((x >> 8) & 0xff00ff) + 0x800080) >> 8; |
| x &= 0x00ff00ff; |
| x &= 0x00ff00ff; |
| |
| |
| dest32[2] = x | t; |
| dest32[2] = x | t; |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void interpolate_pixel_4(DST *dest, quint8 a, |
| inline void interpolate_pixel_4(DST *dest, quint8 a, |
| const SRC *src, quint8 b) |
| const SRC *src, quint8 b) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| dest[0] = dest[0].byte_mul(a) + DST(src[0]).byte_mul(b); |
| 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[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[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); |
| dest[3] = dest[3].byte_mul(a) + DST(src[3]).byte_mul(b); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void blend_sourceOver_4(DST *dest, const SRC *src) |
| inline void blend_sourceOver_4(DST *dest, const SRC *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = alpha_4(src); |
| const quint32 a = alpha_4(src); |
| if (a == 0xffffffff) { |
| if (a == 0xffffffff) { |
| qt_memconvert(dest, src, 4); |
| qt_memconvert(dest, src, 4); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| quint32 buf[3]; // array of quint32 to get correct alignment |
| quint32 buf[3]; // array of quint32 to get correct alignment |
| qt_memconvert((DST*)(void*)buf, src, 4); |
| qt_memconvert((DST*)(void*)buf, src, 4); |
| madd_4(dest, eff_ialpha_4(a, dest), (DST*)(void*)buf); |
| madd_4(dest, eff_ialpha_4(a, dest), (DST*)(void*)buf); |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src) |
| inline void blend_sourceOver_4(qargb8565 *dest, const qargb8565 *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = alpha_4(src); |
| const quint32 a = alpha_4(src); |
| if (a == 0xffffffff) { |
| if (a == 0xffffffff) { |
| qt_memconvert(dest, src, 4); |
| qt_memconvert(dest, src, 4); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src) |
| inline void blend_sourceOver_4(qargb8555 *dest, const qargb8555 *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = alpha_4(src); |
| const quint32 a = alpha_4(src); |
| if (a == 0xffffffff) { |
| if (a == 0xffffffff) { |
| qt_memconvert(dest, src, 4); |
| qt_memconvert(dest, src, 4); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src) |
| inline void blend_sourceOver_4(qargb6666 *dest, const qargb6666 *src) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(dest) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| Q_ASSERT((quintptr(src) & 0x3) == 0); |
| |
| |
| const quint32 a = alpha_4(src); |
| const quint32 a = alpha_4(src); |
| if (a == 0xffffffff) { |
| if (a == 0xffffffff) { |
| qt_memconvert(dest, src, 4); |
| qt_memconvert(dest, src, 4); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| madd_4(dest, eff_ialpha_4(a, dest), src); |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| void QT_FASTCALL blendUntransformed_unaligned(DST *dest, const SRC *src, |
| void QT_FASTCALL blendUntransformed_unaligned(DST *dest, const SRC *src, |
| quint8 coverage, int length) |
| quint8 coverage, int length) |
| { |
| { |
| Q_ASSERT(coverage > 0); |
| Q_ASSERT(coverage > 0); |
| |
| |
| if (coverage < 255) { |
| if (coverage < 255) { |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| if (src[i].alpha()) { |
| if (src[i].alpha()) { |
| const quint8 alpha = qt_div_255(int(src[i].alpha()) * int(coverage)); |
| const quint8 alpha = qt_div_255(int(src[i].alpha()) * int(coverage)); |
| interpolate_pixel(dest[i], DST::ialpha(alpha), |
| interpolate_pixel(dest[i], DST::ialpha(alpha), |
| src[i], DST::alpha(alpha)); |
| src[i], DST::alpha(alpha)); |
| } |
| } |
| } |
| } |
| } else { |
| } else { |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| if (alpha) { |
| if (alpha) { |
| for (int i = 0; i < length; ++i) |
| for (int i = 0; i < length; ++i) |
| interpolate_pixel(dest[i], ialpha, src[i], alpha); |
| interpolate_pixel(dest[i], ialpha, src[i], alpha); |
| } |
| } |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| Q_ASSERT(coverage == 0xff); |
| Q_ASSERT(coverage == 0xff); |
| Q_ASSERT(SRC::hasAlpha()); |
| Q_ASSERT(SRC::hasAlpha()); |
| |
| |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| for (int i = 0; i < length; ++i) { |
| for (int i = 0; i < length; ++i) { |
| const quint8 a = src->alpha(); |
| const quint8 a = src->alpha(); |
| if (a == 0xff) |
| if (a == 0xff) |
| *dest = DST(*src); |
| *dest = DST(*src); |
| else if (a > 0) { |
| else if (a > 0) { |
| if (DST::hasAlpha()) |
| if (DST::hasAlpha()) |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| else |
| else |
| *dest = DST(SRC(*src).truncedAlpha()) + dest->byte_mul(DST::ialpha(a)); |
| *dest = DST(SRC(*src).truncedAlpha()) + dest->byte_mul(DST::ialpha(a)); |
| } |
| } |
| ++src; |
| ++src; |
| ++dest; |
| ++dest; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src, |
| void QT_FASTCALL blendUntransformed_dest16(DST *dest, const SRC *src, |
| quint8 coverage, int length) |
| quint8 coverage, int length) |
| { |
| { |
| Q_ASSERT(sizeof(DST) == 2); |
| Q_ASSERT(sizeof(DST) == 2); |
| Q_ASSERT(sizeof(SRC) == 2); |
| Q_ASSERT(sizeof(SRC) == 2); |
| Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); |
| Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); |
| Q_ASSERT(coverage > 0); |
| Q_ASSERT(coverage > 0); |
| |
| |
| const int align = quintptr(dest) & 0x3; |
| const int align = quintptr(dest) & 0x3; |
| |
| |
| if (coverage < 255) { |
| if (coverage < 255) { |
| // align |
| // align |
| if (align) { |
| if (align) { |
| const quint8 alpha = SRC::hasAlpha() |
| const quint8 alpha = SRC::hasAlpha() |
| ? qt_div_255(int(src->alpha()) * int(coverage)) |
| ? qt_div_255(int(src->alpha()) * int(coverage)) |
| : coverage; |
| : coverage; |
| if (alpha) { |
| if (alpha) { |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| *src, DST::alpha(alpha)); |
| *src, DST::alpha(alpha)); |
| } |
| } |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| --length; |
| --length; |
| } |
| } |
| |
| |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| while (length >= 2) { |
| while (length >= 2) { |
| const quint16 alpha16 = BYTE_MUL(uint(alpha_2(src)), uint(coverage)); |
| const quint16 alpha16 = BYTE_MUL(uint(alpha_2(src)), uint(coverage)); |
| interpolate_pixel_2(dest, src, alpha16); |
| interpolate_pixel_2(dest, src, alpha16); |
| length -= 2; |
| length -= 2; |
| src += 2; |
| src += 2; |
| dest += 2; |
| dest += 2; |
| } |
| } |
| } else { |
| } else { |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| |
| |
| while (length >= 2) { |
| while (length >= 2) { |
| interpolate_pixel_2(dest, ialpha, src, alpha); |
| interpolate_pixel_2(dest, ialpha, src, alpha); |
| length -= 2; |
| length -= 2; |
| src += 2; |
| src += 2; |
| dest += 2; |
| dest += 2; |
| } |
| } |
| } |
| } |
| |
| |
| // tail |
| // tail |
| if (length) { |
| if (length) { |
| const quint8 alpha = SRC::hasAlpha() |
| const quint8 alpha = SRC::hasAlpha() |
| ? qt_div_255(int(src->alpha()) * int(coverage)) |
| ? qt_div_255(int(src->alpha()) * int(coverage)) |
| : coverage; |
| : coverage; |
| if (alpha) { |
| if (alpha) { |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| *src, DST::alpha(alpha)); |
| *src, DST::alpha(alpha)); |
| } |
| } |
| } |
| } |
| |
| |
| return; |
| return; |
| } |
| } |
| |
| |
| Q_ASSERT(SRC::hasAlpha()); |
| Q_ASSERT(SRC::hasAlpha()); |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| if (align) { |
| if (align) { |
| const quint8 alpha = src->alpha(); |
| const quint8 alpha = src->alpha(); |
| if (alpha == 0xff) |
| if (alpha == 0xff) |
| *dest = DST(*src); |
| *dest = DST(*src); |
| else if (alpha > 0) |
| else if (alpha > 0) |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| --length; |
| --length; |
| } |
| } |
| |
| |
| while (length >= 2) { |
| while (length >= 2) { |
| Q_ASSERT((quintptr(dest) & 3) == 0); |
| Q_ASSERT((quintptr(dest) & 3) == 0); |
| Q_ASSERT((quintptr(src) & 3) == 0); |
| Q_ASSERT((quintptr(src) & 3) == 0); |
| |
| |
| const quint16 a = alpha_2(src); |
| const quint16 a = alpha_2(src); |
| if (a == 0xffff) { |
| if (a == 0xffff) { |
| qt_memconvert(dest, src, 2); |
| qt_memconvert(dest, src, 2); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| quint32 buf; |
| quint32 buf; |
| if (sizeof(DST) == 2) |
| if (sizeof(DST) == 2) |
| qt_memconvert((DST*)(void*)&buf, src, 2); |
| qt_memconvert((DST*)(void*)&buf, src, 2); |
| madd_2(dest, eff_ialpha_2(a, dest), (DST*)(void*)&buf); |
| madd_2(dest, eff_ialpha_2(a, dest), (DST*)(void*)&buf); |
| } |
| } |
| |
| |
| length -= 2; |
| length -= 2; |
| src += 2; |
| src += 2; |
| dest += 2; |
| dest += 2; |
| } |
| } |
| |
| |
| if (length) { |
| if (length) { |
| const quint8 alpha = src->alpha(); |
| const quint8 alpha = src->alpha(); |
| if (alpha == 0xff) |
| if (alpha == 0xff) |
| *dest = DST(*src); |
| *dest = DST(*src); |
| else if (alpha > 0) |
| else if (alpha > 0) |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(alpha)); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src, |
| void QT_FASTCALL blendUntransformed_dest24(DST *dest, const SRC *src, |
| quint8 coverage, int length) |
| quint8 coverage, int length) |
| { |
| { |
| Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); |
| Q_ASSERT((quintptr(dest) & 0x3) == (quintptr(src) & 0x3)); |
| Q_ASSERT(sizeof(DST) == 3); |
| Q_ASSERT(sizeof(DST) == 3); |
| Q_ASSERT(coverage > 0); |
| Q_ASSERT(coverage > 0); |
| |
| |
| const int align = quintptr(dest) & 0x3; |
| const int align = quintptr(dest) & 0x3; |
| |
| |
| if (coverage < 255) { |
| if (coverage < 255) { |
| // align |
| // align |
| for (int i = 0; i < align; ++i) { |
| for (int i = 0; i < align; ++i) { |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); |
| const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); |
| if (alpha) |
| if (alpha) |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| *src, DST::alpha(alpha)); |
| *src, DST::alpha(alpha)); |
| } else { |
| } else { |
| interpolate_pixel(*dest, DST::ialpha(coverage), |
| interpolate_pixel(*dest, DST::ialpha(coverage), |
| *src, DST::alpha(coverage)); |
| *src, DST::alpha(coverage)); |
| } |
| } |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| --length; |
| --length; |
| } |
| } |
| |
| |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| while (length >= 4) { |
| while (length >= 4) { |
| const quint32 alpha = QT_PREPEND_NAMESPACE(BYTE_MUL)(uint(alpha_4(src)), uint(coverage)); |
| const quint32 alpha = QT_PREPEND_NAMESPACE(BYTE_MUL)(uint(alpha_4(src)), uint(coverage)); |
| if (alpha) |
| if (alpha) |
| interpolate_pixel_4(dest, src, alpha); |
| interpolate_pixel_4(dest, src, alpha); |
| length -= 4; |
| length -= 4; |
| src += 4; |
| src += 4; |
| dest += 4; |
| dest += 4; |
| } |
| } |
| } else { |
| } else { |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 alpha = DST::alpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| const quint8 ialpha = DST::ialpha(coverage); |
| while (length >= 4) { |
| while (length >= 4) { |
| interpolate_pixel_4(dest, ialpha, src, alpha); |
| interpolate_pixel_4(dest, ialpha, src, alpha); |
| length -= 4; |
| length -= 4; |
| src += 4; |
| src += 4; |
| dest += 4; |
| dest += 4; |
| } |
| } |
| } |
| } |
| |
| |
| // tail |
| // tail |
| while (length--) { |
| while (length--) { |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); |
| const quint8 alpha = qt_div_255(int(src->alpha()) * int(coverage)); |
| if (alpha) |
| if (alpha) |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| interpolate_pixel(*dest, DST::ialpha(alpha), |
| *src, DST::alpha(alpha)); |
| *src, DST::alpha(alpha)); |
| } else { |
| } else { |
| interpolate_pixel(*dest, DST::ialpha(coverage), |
| interpolate_pixel(*dest, DST::ialpha(coverage), |
| *src, DST::alpha(coverage)); |
| *src, DST::alpha(coverage)); |
| } |
| } |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| } |
| } |
| |
| |
| return; |
| return; |
| } |
| } |
| |
| |
| |
| |
| Q_ASSERT(coverage == 255); |
| Q_ASSERT(coverage == 255); |
| Q_ASSERT(SRC::hasAlpha()); |
| Q_ASSERT(SRC::hasAlpha()); |
| |
| |
| if (SRC::hasAlpha()) { |
| if (SRC::hasAlpha()) { |
| // align |
| // align |
| for (int i = 0; i < align; ++i) { |
| for (int i = 0; i < align; ++i) { |
| const quint8 a = src->alpha(); |
| const quint8 a = src->alpha(); |
| if (a == 0xff) { |
| if (a == 0xff) { |
| *dest = DST(*src); |
| *dest = DST(*src); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| } |
| } |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| --length; |
| --length; |
| } |
| } |
| |
| |
| while (length >= 4) { |
| while (length >= 4) { |
| blend_sourceOver_4(dest, src); |
| blend_sourceOver_4(dest, src); |
| length -= 4; |
| length -= 4; |
| src += 4; |
| src += 4; |
| dest += 4; |
| dest += 4; |
| } |
| } |
| |
| |
| // tail |
| // tail |
| while (length--) { |
| while (length--) { |
| const quint8 a = src->alpha(); |
| const quint8 a = src->alpha(); |
| if (a == 0xff) { |
| if (a == 0xff) { |
| *dest = DST(*src); |
| *dest = DST(*src); |
| } else if (a > 0) { |
| } else if (a > 0) { |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| *dest = DST(*src).truncedAlpha() + dest->byte_mul(DST::ialpha(a)); |
| } |
| } |
| ++dest; |
| ++dest; |
| ++src; |
| ++src; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| Q_STATIC_TEMPLATE_SPECIALIZATION |
| void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userData) |
| void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| |
| |
| if (mode != QPainter::CompositionMode_SourceOver && |
| if (mode != QPainter::CompositionMode_SourceOver && |
| mode != QPainter::CompositionMode_Source) |
| mode != QPainter::CompositionMode_Source) |
| { |
| { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| const bool modeSource = !SRC::hasAlpha() || |
| const bool modeSource = !SRC::hasAlpha() || |
| mode == QPainter::CompositionMode_Source; |
| mode == QPainter::CompositionMode_Source; |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx); |
| int xoff = -qRound(-data->dx); |
| int yoff = -qRound(-data->dy); |
| int yoff = -qRound(-data->dy); |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = xoff + x; |
| int sx = xoff + x; |
| int sy = yoff + spans->y; |
| int sy = yoff + spans->y; |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sy >= 0 && sy < image_height && sx < image_width) { |
| if (sx < 0) { |
| if (sx < 0) { |
| x -= sx; |
| x -= sx; |
| length += sx; |
| length += sx; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| if (sx + length > image_width) |
| if (sx + length > image_width) |
| length = image_width - sx; |
| length = image_width - sx; |
| if (length > 0) { |
| if (length > 0) { |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| if (modeSource && coverage == 255) { |
| if (modeSource && coverage == 255) { |
| qt_memconvert<DST, SRC>(dest, src, length); |
| qt_memconvert<DST, SRC>(dest, src, length); |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && length >= 3 && |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && length >= 3 && |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, src, coverage, length); |
| blendUntransformed_dest24(dest, src, coverage, length); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && length >= 3 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && length >= 3 && |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| { |
| { |
| blendUntransformed_dest16(dest, src, coverage, length); |
| blendUntransformed_dest16(dest, src, coverage, length); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, src, coverage, length); |
| blendUntransformed_unaligned(dest, src, coverage, length); |
| } |
| } |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| static void blend_untransformed_rgb888(int count, const QSpan *spans, |
| static void blend_untransformed_rgb888(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_24) |
| #if defined(QT_QWS_DEPTH_24) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB888) |
| if (data->texture.format == QImage::Format_RGB888) |
| blendUntransformed<qrgb888, qrgb888>(count, spans, userData); |
| blendUntransformed<qrgb888, qrgb888>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_argb6666(int count, const QSpan *spans, |
| static void blend_untransformed_argb6666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendUntransformed<qargb6666, qargb6666>(count, spans, userData); |
| blendUntransformed<qargb6666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendUntransformed<qargb6666, qrgb666>(count, spans, userData); |
| blendUntransformed<qargb6666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_rgb666(int count, const QSpan *spans, |
| static void blend_untransformed_rgb666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendUntransformed<qrgb666, qargb6666>(count, spans, userData); |
| blendUntransformed<qrgb666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendUntransformed<qrgb666, qrgb666>(count, spans, userData); |
| blendUntransformed<qrgb666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_argb8565(int count, const QSpan *spans, |
| static void blend_untransformed_argb8565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_16) |
| #if defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendUntransformed<qargb8565, qargb8565>(count, spans, userData); |
| blendUntransformed<qargb8565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendUntransformed<qargb8565, qrgb565>(count, spans, userData); |
| blendUntransformed<qargb8565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_rgb565(int count, const QSpan *spans, |
| static void blend_untransformed_rgb565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendUntransformed<qrgb565, qargb8565>(count, spans, userData); |
| blendUntransformed<qrgb565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendUntransformed<qrgb565, qrgb565>(count, spans, userData); |
| blendUntransformed<qrgb565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_argb8555(int count, const QSpan *spans, |
| static void blend_untransformed_argb8555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendUntransformed<qargb8555, qargb8555>(count, spans, userData); |
| blendUntransformed<qargb8555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendUntransformed<qargb8555, qrgb555>(count, spans, userData); |
| blendUntransformed<qargb8555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_rgb555(int count, const QSpan *spans, |
| static void blend_untransformed_rgb555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendUntransformed<qrgb555, qargb8555>(count, spans, userData); |
| blendUntransformed<qrgb555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendUntransformed<qrgb555, qrgb555>(count, spans, userData); |
| blendUntransformed<qrgb555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_argb4444(int count, const QSpan *spans, |
| static void blend_untransformed_argb4444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendUntransformed<qargb4444, qargb4444>(count, spans, userData); |
| blendUntransformed<qargb4444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendUntransformed<qargb4444, qrgb444>(count, spans, userData); |
| blendUntransformed<qargb4444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_untransformed_rgb444(int count, const QSpan *spans, |
| static void blend_untransformed_rgb444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendUntransformed<qrgb444, qargb4444>(count, spans, userData); |
| blendUntransformed<qrgb444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendUntransformed<qrgb444, qrgb444>(count, spans, userData); |
| blendUntransformed<qrgb444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| blend_untransformed_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| uint src_buffer[buffer_size]; |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx) % image_width; |
| int xoff = -qRound(-data->dx) % image_width; |
| int yoff = -qRound(-data->dy) % image_height; |
| int yoff = -qRound(-data->dy) % image_height; |
| |
| |
| if (xoff < 0) |
| if (xoff < 0) |
| xoff += image_width; |
| xoff += image_width; |
| if (yoff < 0) |
| if (yoff < 0) |
| yoff += image_height; |
| yoff += image_height; |
| |
| |
| while (count--) { |
| while (count--) { |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = (xoff + spans->x) % image_width; |
| int sx = (xoff + spans->x) % image_width; |
| int sy = (spans->y + yoff) % image_height; |
| int sy = (spans->y + yoff) % image_height; |
| if (sx < 0) |
| if (sx < 0) |
| sx += image_width; |
| sx += image_width; |
| if (sy < 0) |
| if (sy < 0) |
| sy += image_height; |
| sy += image_height; |
| |
| |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| while (length) { |
| while (length) { |
| int l = qMin(image_width - sx, length); |
| int l = qMin(image_width - sx, length); |
| if (buffer_size < l) |
| if (buffer_size < l) |
| l = buffer_size; |
| l = buffer_size; |
| const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); |
| const uint *src = op.src_fetch(src_buffer, &op, data, sy, sx, l); |
| if (spanMethod == RegularSpans) { |
| if (spanMethod == RegularSpans) { |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer; |
| op.func(dest, src, l, coverage); |
| op.func(dest, src, l, coverage); |
| if (op.dest_store) |
| if (op.dest_store) |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| op.dest_store(data->rasterBuffer, x, spans->y, dest, l); |
| } else { |
| } else { |
| drawBufferSpan(data, src, l, x, spans->y, l, |
| drawBufferSpan(data, src, l, x, spans->y, l, |
| coverage); |
| coverage); |
| } |
| } |
| x += l; |
| x += l; |
| sx += l; |
| sx += l; |
| length -= l; |
| length -= l; |
| if (sx >= image_width) |
| if (sx >= image_width) |
| sx = 0; |
| sx = 0; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| && data->texture.format != QImage::Format_RGB32) { |
| && data->texture.format != QImage::Format_RGB32) { |
| blend_tiled_generic<spanMethod>(count, spans, userData); |
| blend_tiled_generic<spanMethod>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| Operator op = getOperator(data, spans, count); |
| Operator op = getOperator(data, spans, count); |
| |
| |
| int image_width = data->texture.width; |
| int image_width = data->texture.width; |
| int image_height = data->texture.height; |
| int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx) % image_width; |
| int xoff = -qRound(-data->dx) % image_width; |
| int yoff = -qRound(-data->dy) % image_height; |
| int yoff = -qRound(-data->dy) % image_height; |
| |
| |
| if (xoff < 0) |
| if (xoff < 0) |
| xoff += image_width; |
| xoff += image_width; |
| if (yoff < 0) |
| if (yoff < 0) |
| yoff += image_height; |
| yoff += image_height; |
| |
| |
| while (count--) { |
| while (count--) { |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = (xoff + spans->x) % image_width; |
| int sx = (xoff + spans->x) % image_width; |
| int sy = (spans->y + yoff) % image_height; |
| int sy = (spans->y + yoff) % image_height; |
| if (sx < 0) |
| if (sx < 0) |
| sx += image_width; |
| sx += image_width; |
| if (sy < 0) |
| if (sy < 0) |
| sy += image_height; |
| sy += image_height; |
| |
| |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| while (length) { |
| while (length) { |
| int l = qMin(image_width - sx, length); |
| int l = qMin(image_width - sx, length); |
| if (buffer_size < l) |
| if (buffer_size < l) |
| l = buffer_size; |
| l = buffer_size; |
| const uint *src = (uint *)data->texture.scanLine(sy) + sx; |
| const uint *src = (uint *)data->texture.scanLine(sy) + sx; |
| if (spanMethod == RegularSpans) { |
| if (spanMethod == RegularSpans) { |
| uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; |
| uint *dest = ((uint *)data->rasterBuffer->scanLine(spans->y)) + x; |
| op.func(dest, src, l, coverage); |
| op.func(dest, src, l, coverage); |
| } else { |
| } else { |
| drawBufferSpan(data, src, buffer_size, |
| drawBufferSpan(data, src, buffer_size, |
| x, spans->y, l, coverage); |
| x, spans->y, l, coverage); |
| } |
| } |
| x += l; |
| x += l; |
| length -= l; |
| length -= l; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| |
| |
| if (mode != QPainter::CompositionMode_SourceOver && |
| if (mode != QPainter::CompositionMode_SourceOver && |
| mode != QPainter::CompositionMode_Source) |
| mode != QPainter::CompositionMode_Source) |
| { |
| { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| const bool modeSource = !SRC::hasAlpha() || |
| const bool modeSource = !SRC::hasAlpha() || |
| mode == QPainter::CompositionMode_Source; |
| mode == QPainter::CompositionMode_Source; |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| int xoff = -qRound(-data->dx) % image_width; |
| int xoff = -qRound(-data->dx) % image_width; |
| int yoff = -qRound(-data->dy) % image_height; |
| int yoff = -qRound(-data->dy) % image_height; |
| |
| |
| if (xoff < 0) |
| if (xoff < 0) |
| xoff += image_width; |
| xoff += image_width; |
| if (yoff < 0) |
| if (yoff < 0) |
| yoff += image_height; |
| yoff += image_height; |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| int x = spans->x; |
| int x = spans->x; |
| int length = spans->len; |
| int length = spans->len; |
| int sx = (xoff + spans->x) % image_width; |
| int sx = (xoff + spans->x) % image_width; |
| int sy = (spans->y + yoff) % image_height; |
| int sy = (spans->y + yoff) % image_height; |
| if (sx < 0) |
| if (sx < 0) |
| sx += image_width; |
| sx += image_width; |
| if (sy < 0) |
| if (sy < 0) |
| sy += image_height; |
| sy += image_height; |
| |
| |
| if (modeSource && coverage == 255) { |
| if (modeSource && coverage == 255) { |
| // Copy the first texture block |
| // Copy the first texture block |
| length = qMin(image_width,length); |
| length = qMin(image_width,length); |
| int tx = x; |
| int tx = x; |
| while (length) { |
| while (length) { |
| int l = qMin(image_width - sx, length); |
| int l = qMin(image_width - sx, length); |
| if (buffer_size < l) |
| if (buffer_size < l) |
| l = buffer_size; |
| l = buffer_size; |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + tx; |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + tx; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| |
| |
| qt_memconvert<DST, SRC>(dest, src, l); |
| qt_memconvert<DST, SRC>(dest, src, l); |
| length -= l; |
| length -= l; |
| tx += l; |
| tx += l; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| |
| |
| // Now use the rasterBuffer as the source of the texture, |
| // Now use the rasterBuffer as the source of the texture, |
| // We can now progressively copy larger blocks |
| // We can now progressively copy larger blocks |
| // - Less cpu time in code figuring out what to copy |
| // - Less cpu time in code figuring out what to copy |
| // We are dealing with one block of data |
| // We are dealing with one block of data |
| // - More likely to fit in the cache |
| // - More likely to fit in the cache |
| // - can use memcpy |
| // - can use memcpy |
| int copy_image_width = qMin(image_width, int(spans->len)); |
| int copy_image_width = qMin(image_width, int(spans->len)); |
| length = spans->len - copy_image_width; |
| length = spans->len - copy_image_width; |
| DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| DST *dest = src + copy_image_width; |
| DST *dest = src + copy_image_width; |
| while (copy_image_width < length) { |
| while (copy_image_width < length) { |
| qt_memconvert(dest, src, copy_image_width); |
| qt_memconvert(dest, src, copy_image_width); |
| dest += copy_image_width; |
| dest += copy_image_width; |
| length -= copy_image_width; |
| length -= copy_image_width; |
| copy_image_width *= 2; |
| copy_image_width *= 2; |
| } |
| } |
| if (length > 0) |
| if (length > 0) |
| qt_memconvert(dest, src, length); |
| qt_memconvert(dest, src, length); |
| } else { |
| } else { |
| while (length) { |
| while (length) { |
| int l = qMin(image_width - sx, length); |
| int l = qMin(image_width - sx, length); |
| if (buffer_size < l) |
| if (buffer_size < l) |
| l = buffer_size; |
| l = buffer_size; |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; |
| if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, src, coverage, l); |
| blendUntransformed_dest24(dest, src, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| (quintptr(dest) & 3) == (quintptr(src) & 3)) |
| { |
| { |
| blendUntransformed_dest16(dest, src, coverage, l); |
| blendUntransformed_dest16(dest, src, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, src, coverage, l); |
| blendUntransformed_unaligned(dest, src, coverage, l); |
| } |
| } |
| |
| |
| x += l; |
| x += l; |
| length -= l; |
| length -= l; |
| sx = 0; |
| sx = 0; |
| } |
| } |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| |
| |
| static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_24) |
| #if defined(QT_QWS_DEPTH_24) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB888) |
| if (data->texture.format == QImage::Format_RGB888) |
| blendTiled<qrgb888, qrgb888>(count, spans, userData); |
| blendTiled<qrgb888, qrgb888>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTiled<qargb6666, qargb6666>(count, spans, userData); |
| blendTiled<qargb6666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTiled<qargb6666, qrgb666>(count, spans, userData); |
| blendTiled<qargb6666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTiled<qrgb666, qargb6666>(count, spans, userData); |
| blendTiled<qrgb666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTiled<qrgb666, qrgb666>(count, spans, userData); |
| blendTiled<qrgb666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_16) |
| #if defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTiled<qargb8565, qargb8565>(count, spans, userData); |
| blendTiled<qargb8565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTiled<qargb8565, qrgb565>(count, spans, userData); |
| blendTiled<qargb8565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTiled<qrgb565, qargb8565>(count, spans, userData); |
| blendTiled<qrgb565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTiled<qrgb565, qrgb565>(count, spans, userData); |
| blendTiled<qrgb565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTiled<qargb8555, qargb8555>(count, spans, userData); |
| blendTiled<qargb8555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTiled<qargb8555, qrgb555>(count, spans, userData); |
| blendTiled<qargb8555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTiled<qrgb555, qargb8555>(count, spans, userData); |
| blendTiled<qrgb555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTiled<qrgb555, qrgb555>(count, spans, userData); |
| blendTiled<qrgb555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTiled<qargb4444, qargb4444>(count, spans, userData); |
| blendTiled<qargb4444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTiled<qargb4444, qrgb444>(count, spans, userData); |
| blendTiled<qargb4444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) |
| static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTiled<qrgb444, qargb4444>(count, spans, userData); |
| blendTiled<qrgb444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTiled<qrgb444, qrgb444>(count, spans, userData); |
| blendTiled<qrgb444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| blend_tiled_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan *spans, |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| |
| |
| |
| |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| SRC buffer[buffer_size]; |
| SRC buffer[buffer_size]; |
| |
| |
| const int src_minx = data->texture.x1; |
| const int src_minx = data->texture.x1; |
| const int src_miny = data->texture.y1; |
| const int src_miny = data->texture.y1; |
| const int src_maxx = data->texture.x2 - 1; |
| const int src_maxx = data->texture.x2 - 1; |
| const int src_maxy = data->texture.y2 - 1; |
| const int src_maxy = data->texture.y2 - 1; |
| |
| |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| int x = int((data->m21 * cy |
| int x = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale) - half_point; |
| + data->m11 * cx + data->dx) * fixed_scale) - half_point; |
| int y = int((data->m22 * cy |
| int y = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale) - half_point; |
| + data->m12 * cx + data->dy) * fixed_scale) - half_point; |
| int length = spans->len; |
| int length = spans->len; |
| |
| |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| |
| |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| int x1 = (x >> 16); |
| int x1 = (x >> 16); |
| int x2; |
| int x2; |
| int y1 = (y >> 16); |
| int y1 = (y >> 16); |
| int y2; |
| int y2; |
| |
| |
| const int distx = (x & 0x0000ffff) >> 8; |
| const int distx = (x & 0x0000ffff) >> 8; |
| const int disty = (y & 0x0000ffff) >> 8; |
| const int disty = (y & 0x0000ffff) >> 8; |
| |
| |
| if (x1 < src_minx) { |
| if (x1 < src_minx) { |
| x2 = x1 = src_minx; |
| x2 = x1 = src_minx; |
| } else if (x1 >= src_maxx) { |
| } else if (x1 >= src_maxx) { |
| x2 = x1 = src_maxx; |
| x2 = x1 = src_maxx; |
| } else { |
| } else { |
| x2 = x1 + 1; |
| x2 = x1 + 1; |
| } |
| } |
| if (y1 < src_miny) { |
| if (y1 < src_miny) { |
| y2 = y1 = src_miny; |
| y2 = y1 = src_miny; |
| } else if (y1 >= src_maxy) { |
| } else if (y1 >= src_maxy) { |
| y2 = y1 = src_maxy; |
| y2 = y1 = src_maxy; |
| } else { |
| } else { |
| y2 = y1 + 1; |
| y2 = y1 + 1; |
| } |
| } |
| #if 0 |
| #if 0 |
| if (x1 == x2) { |
| if (x1 == x2) { |
| if (y1 == y2) { |
| if (y1 == y2) { |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| } else { |
| } else { |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| const SRC t = data->texture.scanLine(y2)[x1]; |
| const SRC t = data->texture.scanLine(y2)[x1]; |
| interpolate_pixel(*b, SRC::ialpha(disty), |
| interpolate_pixel(*b, SRC::ialpha(disty), |
| t, SRC::alpha(disty)); |
| t, SRC::alpha(disty)); |
| } |
| } |
| } else if (y1 == y2) { |
| } else if (y1 == y2) { |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| *b = ((SRC*)data->texture.scanLine(y1))[x1]; |
| const SRC t = ((SRC*)data->texture.scanLine(y1))[x2]; |
| const SRC t = ((SRC*)data->texture.scanLine(y1))[x2]; |
| interpolate_pixel(*b, SRC::ialpha(distx), |
| interpolate_pixel(*b, SRC::ialpha(distx), |
| t, SRC::alpha(distx)); |
| t, SRC::alpha(distx)); |
| } else |
| } else |
| #endif |
| #endif |
| { |
| { |
| const SRC *src1 = (SRC*)data->texture.scanLine(y1); |
| const SRC *src1 = (SRC*)data->texture.scanLine(y1); |
| const SRC *src2 = (SRC*)data->texture.scanLine(y2); |
| const SRC *src2 = (SRC*)data->texture.scanLine(y2); |
| SRC tl = src1[x1]; |
| SRC tl = src1[x1]; |
| const SRC tr = src1[x2]; |
| const SRC tr = src1[x2]; |
| SRC bl = src2[x1]; |
| SRC bl = src2[x1]; |
| const SRC br = src2[x2]; |
| const SRC br = src2[x2]; |
| const quint8 ax = SRC::alpha(distx); |
| const quint8 ax = SRC::alpha(distx); |
| const quint8 iax = SRC::ialpha(distx); |
| const quint8 iax = SRC::ialpha(distx); |
| |
| |
| interpolate_pixel(tl, iax, tr, ax); |
| interpolate_pixel(tl, iax, tr, ax); |
| interpolate_pixel(bl, iax, br, ax); |
| interpolate_pixel(bl, iax, br, ax); |
| interpolate_pixel(tl, SRC::ialpha(disty), |
| interpolate_pixel(tl, SRC::ialpha(disty), |
| bl, SRC::alpha(disty)); |
| bl, SRC::alpha(disty)); |
| *b = tl; |
| *b = tl; |
| } |
| } |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| } |
| } |
| |
| |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| |
| |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| |
| |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal px = x * iw - qreal(0.5); |
| const qreal px = x * iw - qreal(0.5); |
| const qreal py = y * iw - qreal(0.5); |
| const qreal py = y * iw - qreal(0.5); |
| |
| |
| int x1 = int(px) - (px < 0); |
| int x1 = int(px) - (px < 0); |
| int x2; |
| int x2; |
| int y1 = int(py) - (py < 0); |
| int y1 = int(py) - (py < 0); |
| int y2; |
| int y2; |
| |
| |
| const int distx = int((px - x1) * 256); |
| const int distx = int((px - x1) * 256); |
| const int disty = int((py - y1) * 256); |
| const int disty = int((py - y1) * 256); |
| |
| |
| if (x1 < src_minx) { |
| if (x1 < src_minx) { |
| x2 = x1 = src_minx; |
| x2 = x1 = src_minx; |
| } else if (x1 >= src_maxx) { |
| } else if (x1 >= src_maxx) { |
| x2 = x1 = src_maxx; |
| x2 = x1 = src_maxx; |
| } else { |
| } else { |
| x2 = x1 + 1; |
| x2 = x1 + 1; |
| } |
| } |
| if (y1 < src_miny) { |
| if (y1 < src_miny) { |
| y2 = y1 = src_miny; |
| y2 = y1 = src_miny; |
| } else if (y1 >= src_maxy) { |
| } else if (y1 >= src_maxy) { |
| y2 = y1 = src_maxy; |
| y2 = y1 = src_maxy; |
| } else { |
| } else { |
| y2 = y1 + 1; |
| y2 = y1 + 1; |
| } |
| } |
| |
| |
| const SRC *src1 = (SRC*)data->texture.scanLine(y1); |
| const SRC *src1 = (SRC*)data->texture.scanLine(y1); |
| const SRC *src2 = (SRC*)data->texture.scanLine(y2); |
| const SRC *src2 = (SRC*)data->texture.scanLine(y2); |
| SRC tl = src1[x1]; |
| SRC tl = src1[x1]; |
| const SRC tr = src1[x2]; |
| const SRC tr = src1[x2]; |
| SRC bl = src2[x1]; |
| SRC bl = src2[x1]; |
| const SRC br = src2[x2]; |
| const SRC br = src2[x2]; |
| const quint8 ax = SRC::alpha(distx); |
| const quint8 ax = SRC::alpha(distx); |
| const quint8 iax = SRC::ialpha(distx); |
| const quint8 iax = SRC::ialpha(distx); |
| |
| |
| interpolate_pixel(tl, iax, tr, ax); |
| interpolate_pixel(tl, iax, tr, ax); |
| interpolate_pixel(bl, iax, br, ax); |
| interpolate_pixel(bl, iax, br, ax); |
| interpolate_pixel(tl, SRC::ialpha(disty), |
| interpolate_pixel(tl, SRC::ialpha(disty), |
| bl, SRC::alpha(disty)); |
| bl, SRC::alpha(disty)); |
| *b = tl; |
| *b = tl; |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| w += fdw; |
| w += fdw; |
| } |
| } |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_24) |
| #if defined(QT_QWS_DEPTH_24) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB888) |
| if (data->texture.format == QImage::Format_RGB888) |
| blendTransformedBilinear<qrgb888, qrgb888>(count, spans, userData); |
| blendTransformedBilinear<qrgb888, qrgb888>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformedBilinear<qargb6666, qargb6666>(count, spans, userData); |
| blendTransformedBilinear<qargb6666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformedBilinear<qargb6666, qrgb666>(count, spans, userData); |
| blendTransformedBilinear<qargb6666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformedBilinear<qrgb666, qargb6666>(count, spans, userData); |
| blendTransformedBilinear<qrgb666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformedBilinear<qrgb666, qrgb666>(count, spans, userData); |
| blendTransformedBilinear<qrgb666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_16) |
| #if defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformedBilinear<qargb8565, qargb8565>(count, spans, userData); |
| blendTransformedBilinear<qargb8565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTransformedBilinear<qargb8565, qrgb565>(count, spans, userData); |
| blendTransformedBilinear<qargb8565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, |
| static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB16) |
| if (data->texture.format == QImage::Format_RGB16) |
| blendTransformedBilinear<qrgb565, qrgb565>(count, spans, userData); |
| blendTransformedBilinear<qrgb565, qrgb565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| else if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData); |
| blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformedBilinear<qargb8555, qargb8555>(count, spans, userData); |
| blendTransformedBilinear<qargb8555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformedBilinear<qargb8555, qrgb555>(count, spans, userData); |
| blendTransformedBilinear<qargb8555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformedBilinear<qrgb555, qargb8555>(count, spans, userData); |
| blendTransformedBilinear<qrgb555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformedBilinear<qrgb555, qrgb555>(count, spans, userData); |
| blendTransformedBilinear<qrgb555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformedBilinear<qargb4444, qargb4444>(count, spans, userData); |
| blendTransformedBilinear<qargb4444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformedBilinear<qargb4444, qrgb444>(count, spans, userData); |
| blendTransformedBilinear<qargb4444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData) |
| static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformedBilinear<qrgb444, qargb4444>(count, spans, userData); |
| blendTransformedBilinear<qrgb444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData); |
| blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| && data->texture.format != QImage::Format_RGB32) { |
| && data->texture.format != QImage::Format_RGB32) { |
| blend_src_generic<spanMethod>(count, spans, userData); |
| blend_src_generic<spanMethod>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; |
| CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| |
| |
| int image_width = data->texture.width; |
| int image_width = data->texture.width; |
| int image_height = data->texture.height; |
| int image_height = data->texture.height; |
| const int scanline_offset = data->texture.bytesPerLine / 4; |
| const int scanline_offset = data->texture.bytesPerLine / 4; |
| |
| |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| while (count--) { |
| while (count--) { |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| |
| |
| uint *target = ((uint *)t) + spans->x; |
| uint *target = ((uint *)t) + spans->x; |
| uint *image_bits = (uint *)data->texture.imageData; |
| uint *image_bits = (uint *)data->texture.imageData; |
| |
| |
| const qreal cx = spans->x + 0.5; |
| const qreal cx = spans->x + 0.5; |
| const qreal cy = spans->y + 0.5; |
| const qreal cy = spans->y + 0.5; |
| |
| |
| int x = int((data->m21 * cy |
| int x = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int y = int((data->m22 * cy |
| int y = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| |
| |
| int length = spans->len; |
| int length = spans->len; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| while (length) { |
| while (length) { |
| int l = qMin(length, buffer_size); |
| int l = qMin(length, buffer_size); |
| const uint *end = buffer + l; |
| const uint *end = buffer + l; |
| uint *b = buffer; |
| uint *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| int px = x >> 16; |
| int px = x >> 16; |
| int py = y >> 16; |
| int py = y >> 16; |
| |
| |
| bool out = (px < 0) || (px >= image_width) |
| bool out = (px < 0) || (px >= image_width) |
| || (py < 0) || (py >= image_height); |
| || (py < 0) || (py >= image_height); |
| |
| |
| int y_offset = py * scanline_offset; |
| int y_offset = py * scanline_offset; |
| *b = out ? uint(0) : image_bits[y_offset + px]; |
| *b = out ? uint(0) : image_bits[y_offset + px]; |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| ++b; |
| ++b; |
| } |
| } |
| if (spanMethod == RegularSpans) |
| if (spanMethod == RegularSpans) |
| func(target, buffer, l, coverage); |
| func(target, buffer, l, coverage); |
| else |
| else |
| drawBufferSpan(data, buffer, buffer_size, |
| drawBufferSpan(data, buffer, buffer_size, |
| spans->x + spans->len - length, |
| spans->x + spans->len - length, |
| spans->y, l, coverage); |
| spans->y, l, coverage); |
| target += l; |
| target += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| while (count--) { |
| while (count--) { |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| |
| |
| uint *target = ((uint *)t) + spans->x; |
| uint *target = ((uint *)t) + spans->x; |
| uint *image_bits = (uint *)data->texture.imageData; |
| uint *image_bits = (uint *)data->texture.imageData; |
| |
| |
| const qreal cx = spans->x + 0.5; |
| const qreal cx = spans->x + 0.5; |
| const qreal cy = spans->y + 0.5; |
| const qreal cy = spans->y + 0.5; |
| |
| |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| int length = spans->len; |
| int length = spans->len; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| while (length) { |
| while (length) { |
| int l = qMin(length, buffer_size); |
| int l = qMin(length, buffer_size); |
| const uint *end = buffer + l; |
| const uint *end = buffer + l; |
| uint *b = buffer; |
| uint *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal tx = x * iw; |
| const qreal tx = x * iw; |
| const qreal ty = y * iw; |
| const qreal ty = y * iw; |
| const int px = int(tx) - (tx < 0); |
| const int px = int(tx) - (tx < 0); |
| const int py = int(ty) - (ty < 0); |
| const int py = int(ty) - (ty < 0); |
| |
| |
| bool out = (px < 0) || (px >= image_width) |
| bool out = (px < 0) || (px >= image_width) |
| || (py < 0) || (py >= image_height); |
| || (py < 0) || (py >= image_height); |
| |
| |
| int y_offset = py * scanline_offset; |
| int y_offset = py * scanline_offset; |
| *b = out ? uint(0) : image_bits[y_offset + px]; |
| *b = out ? uint(0) : image_bits[y_offset + px]; |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| w += fdw; |
| w += fdw; |
| |
| |
| ++b; |
| ++b; |
| } |
| } |
| if (spanMethod == RegularSpans) |
| if (spanMethod == RegularSpans) |
| func(target, buffer, l, coverage); |
| func(target, buffer, l, coverage); |
| else |
| else |
| drawBufferSpan(data, buffer, buffer_size, |
| drawBufferSpan(data, buffer, buffer_size, |
| spans->x + spans->len - length, |
| spans->x + spans->len - length, |
| spans->y, l, coverage); |
| spans->y, l, coverage); |
| target += l; |
| target += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| |
| |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| SRC buffer[buffer_size]; |
| SRC buffer[buffer_size]; |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| |
| |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| int x = int((data->m21 * cy |
| int x = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int y = int((data->m22 * cy |
| int y = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| int length = spans->len; |
| int length = spans->len; |
| |
| |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| |
| |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const int px = (x >> 16); |
| const int px = (x >> 16); |
| const int py = (y >> 16); |
| const int py = (y >> 16); |
| |
| |
| if ((px < 0) || (px >= image_width) || |
| if ((px < 0) || (px >= image_width) || |
| (py < 0) || (py >= image_height)) |
| (py < 0) || (py >= image_height)) |
| { |
| { |
| *b = 0; |
| *b = 0; |
| } else { |
| } else { |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| } |
| } |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| } |
| } |
| |
| |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| |
| |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| |
| |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal tx = x * iw; |
| const qreal tx = x * iw; |
| const qreal ty = y * iw; |
| const qreal ty = y * iw; |
| |
| |
| const int px = int(tx) - (tx < 0); |
| const int px = int(tx) - (tx < 0); |
| const int py = int(ty) - (ty < 0); |
| const int py = int(ty) - (ty < 0); |
| |
| |
| if ((px < 0) || (px >= image_width) || |
| if ((px < 0) || (px >= image_width) || |
| (py < 0) || (py >= image_height)) |
| (py < 0) || (py >= image_height)) |
| { |
| { |
| *b = 0; |
| *b = 0; |
| } else { |
| } else { |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| } |
| } |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| w += fdw; |
| w += fdw; |
| } |
| } |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void blend_transformed_rgb888(int count, const QSpan *spans, |
| static void blend_transformed_rgb888(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_24) |
| #if defined(QT_QWS_DEPTH_24) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB888) |
| if (data->texture.format == QImage::Format_RGB888) |
| blendTransformed<qrgb888, qrgb888>(count, spans, userData); |
| blendTransformed<qrgb888, qrgb888>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_argb6666(int count, const QSpan *spans, |
| static void blend_transformed_argb6666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformed<qargb6666, qargb6666>(count, spans, userData); |
| blendTransformed<qargb6666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformed<qargb6666, qrgb666>(count, spans, userData); |
| blendTransformed<qargb6666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_rgb666(int count, const QSpan *spans, |
| static void blend_transformed_rgb666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformed<qrgb666, qargb6666>(count, spans, userData); |
| blendTransformed<qrgb666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformed<qrgb666, qrgb666>(count, spans, userData); |
| blendTransformed<qrgb666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_argb8565(int count, const QSpan *spans, |
| static void blend_transformed_argb8565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_16) |
| #if defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformed<qargb8565, qargb8565>(count, spans, userData); |
| blendTransformed<qargb8565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTransformed<qargb8565, qrgb565>(count, spans, userData); |
| blendTransformed<qargb8565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_rgb565(int count, const QSpan *spans, |
| static void blend_transformed_rgb565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformed<qrgb565, qargb8565>(count, spans, userData); |
| blendTransformed<qrgb565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTransformed<qrgb565, qrgb565>(count, spans, userData); |
| blendTransformed<qrgb565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_argb8555(int count, const QSpan *spans, |
| static void blend_transformed_argb8555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformed<qargb8555, qargb8555>(count, spans, userData); |
| blendTransformed<qargb8555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformed<qargb8555, qrgb555>(count, spans, userData); |
| blendTransformed<qargb8555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_rgb555(int count, const QSpan *spans, |
| static void blend_transformed_rgb555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformed<qrgb555, qargb8555>(count, spans, userData); |
| blendTransformed<qrgb555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformed<qrgb555, qrgb555>(count, spans, userData); |
| blendTransformed<qrgb555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_argb4444(int count, const QSpan *spans, |
| static void blend_transformed_argb4444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformed<qargb4444, qargb4444>(count, spans, userData); |
| blendTransformed<qargb4444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformed<qargb4444, qrgb444>(count, spans, userData); |
| blendTransformed<qargb4444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_rgb444(int count, const QSpan *spans, |
| static void blend_transformed_rgb444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformed<qrgb444, qargb4444>(count, spans, userData); |
| blendTransformed<qrgb444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformed<qrgb444, qrgb444>(count, spans, userData); |
| blendTransformed<qrgb444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| template <SpanMethod spanMethod> |
| template <SpanMethod spanMethod> |
| Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| if (data->texture.format != QImage::Format_ARGB32_Premultiplied |
| && data->texture.format != QImage::Format_RGB32) { |
| && data->texture.format != QImage::Format_RGB32) { |
| blend_src_generic<spanMethod>(count, spans, userData); |
| blend_src_generic<spanMethod>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; |
| CompositionFunction func = functionForMode[data->rasterBuffer->compositionMode]; |
| uint buffer[buffer_size]; |
| uint buffer[buffer_size]; |
| |
| |
| int image_width = data->texture.width; |
| int image_width = data->texture.width; |
| int image_height = data->texture.height; |
| int image_height = data->texture.height; |
| const int scanline_offset = data->texture.bytesPerLine / 4; |
| const int scanline_offset = data->texture.bytesPerLine / 4; |
| |
| |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdx = (int)(data->m11 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| while (count--) { |
| while (count--) { |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| |
| |
| uint *target = ((uint *)t) + spans->x; |
| uint *target = ((uint *)t) + spans->x; |
| uint *image_bits = (uint *)data->texture.imageData; |
| uint *image_bits = (uint *)data->texture.imageData; |
| |
| |
| const qreal cx = spans->x + 0.5; |
| const qreal cx = spans->x + 0.5; |
| const qreal cy = spans->y + 0.5; |
| const qreal cy = spans->y + 0.5; |
| |
| |
| int x = int((data->m21 * cy |
| int x = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int y = int((data->m22 * cy |
| int y = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| |
| |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| int l = qMin(length, buffer_size); |
| int l = qMin(length, buffer_size); |
| const uint *end = buffer + l; |
| const uint *end = buffer + l; |
| uint *b = buffer; |
| uint *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| int px = x >> 16; |
| int px = x >> 16; |
| int py = y >> 16; |
| int py = y >> 16; |
| px %= image_width; |
| px %= image_width; |
| py %= image_height; |
| py %= image_height; |
| if (px < 0) px += image_width; |
| if (px < 0) px += image_width; |
| if (py < 0) py += image_height; |
| if (py < 0) py += image_height; |
| int y_offset = py * scanline_offset; |
| int y_offset = py * scanline_offset; |
| |
| |
| Q_ASSERT(px >= 0 && px < image_width); |
| Q_ASSERT(px >= 0 && px < image_width); |
| Q_ASSERT(py >= 0 && py < image_height); |
| Q_ASSERT(py >= 0 && py < image_height); |
| |
| |
| *b = image_bits[y_offset + px]; |
| *b = image_bits[y_offset + px]; |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| ++b; |
| ++b; |
| } |
| } |
| if (spanMethod == RegularSpans) |
| if (spanMethod == RegularSpans) |
| func(target, buffer, l, coverage); |
| func(target, buffer, l, coverage); |
| else |
| else |
| drawBufferSpan(data, buffer, buffer_size, |
| drawBufferSpan(data, buffer, buffer_size, |
| spans->x + spans->len - length, |
| spans->x + spans->len - length, |
| spans->y, l, coverage); |
| spans->y, l, coverage); |
| target += l; |
| target += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| while (count--) { |
| while (count--) { |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| void *t = data->rasterBuffer->scanLine(spans->y); |
| |
| |
| uint *target = ((uint *)t) + spans->x; |
| uint *target = ((uint *)t) + spans->x; |
| uint *image_bits = (uint *)data->texture.imageData; |
| uint *image_bits = (uint *)data->texture.imageData; |
| |
| |
| const qreal cx = spans->x + 0.5; |
| const qreal cx = spans->x + 0.5; |
| const qreal cy = spans->y + 0.5; |
| const qreal cy = spans->y + 0.5; |
| |
| |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| const int coverage = (spans->coverage * data->texture.const_alpha) >> 8; |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| int l = qMin(length, buffer_size); |
| int l = qMin(length, buffer_size); |
| const uint *end = buffer + l; |
| const uint *end = buffer + l; |
| uint *b = buffer; |
| uint *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal tx = x * iw; |
| const qreal tx = x * iw; |
| const qreal ty = y * iw; |
| const qreal ty = y * iw; |
| int px = int(tx) - (tx < 0); |
| int px = int(tx) - (tx < 0); |
| int py = int(ty) - (ty < 0); |
| int py = int(ty) - (ty < 0); |
| |
| |
| px %= image_width; |
| px %= image_width; |
| py %= image_height; |
| py %= image_height; |
| if (px < 0) px += image_width; |
| if (px < 0) px += image_width; |
| if (py < 0) py += image_height; |
| if (py < 0) py += image_height; |
| int y_offset = py * scanline_offset; |
| int y_offset = py * scanline_offset; |
| |
| |
| Q_ASSERT(px >= 0 && px < image_width); |
| Q_ASSERT(px >= 0 && px < image_width); |
| Q_ASSERT(py >= 0 && py < image_height); |
| Q_ASSERT(py >= 0 && py < image_height); |
| |
| |
| *b = image_bits[y_offset + px]; |
| *b = image_bits[y_offset + px]; |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| w += fdw; |
| w += fdw; |
| //force increment to avoid /0 |
| //force increment to avoid /0 |
| if (!w) { |
| if (!w) { |
| w += fdw; |
| w += fdw; |
| } |
| } |
| ++b; |
| ++b; |
| } |
| } |
| if (spanMethod == RegularSpans) |
| if (spanMethod == RegularSpans) |
| func(target, buffer, l, coverage); |
| func(target, buffer, l, coverage); |
| else |
| else |
| drawBufferSpan(data, buffer, buffer_size, |
| drawBufferSpan(data, buffer, buffer_size, |
| spans->x + spans->len - length, |
| spans->x + spans->len - length, |
| spans->y, l, coverage); |
| spans->y, l, coverage); |
| target += l; |
| target += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *spans, void *userData) |
| Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData*>(userData); |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| QPainter::CompositionMode mode = data->rasterBuffer->compositionMode; |
| |
| |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| if (mode != QPainter::CompositionMode_SourceOver) { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| return; |
| return; |
| } |
| } |
| |
| |
| SRC buffer[buffer_size]; |
| SRC buffer[buffer_size]; |
| const int image_width = data->texture.width; |
| const int image_width = data->texture.width; |
| const int image_height = data->texture.height; |
| const int image_height = data->texture.height; |
| |
| |
| if (data->fast_matrix) { |
| if (data->fast_matrix) { |
| // The increment pr x in the scanline |
| // The increment pr x in the scanline |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdx = (int)(data->m11 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| const int fdy = (int)(data->m12 * fixed_scale); |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| int x = int((data->m21 * cy |
| int x = int((data->m21 * cy |
| + data->m11 * cx + data->dx) * fixed_scale); |
| + data->m11 * cx + data->dx) * fixed_scale); |
| int y = int((data->m22 * cy |
| int y = int((data->m22 * cy |
| + data->m12 * cx + data->dy) * fixed_scale); |
| + data->m12 * cx + data->dy) * fixed_scale); |
| int length = spans->len; |
| int length = spans->len; |
| |
| |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| |
| |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| int px = (x >> 16) % image_width; |
| int px = (x >> 16) % image_width; |
| int py = (y >> 16) % image_height; |
| int py = (y >> 16) % image_height; |
| |
| |
| if (px < 0) |
| if (px < 0) |
| px += image_width; |
| px += image_width; |
| if (py < 0) |
| if (py < 0) |
| py += image_height; |
| py += image_height; |
| |
| |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| } |
| } |
| |
| |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } else { |
| } else { |
| const qreal fdx = data->m11; |
| const qreal fdx = data->m11; |
| const qreal fdy = data->m12; |
| const qreal fdy = data->m12; |
| const qreal fdw = data->m13; |
| const qreal fdw = data->m13; |
| |
| |
| while (count--) { |
| while (count--) { |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| const quint8 coverage = (data->texture.const_alpha * spans->coverage) >> 8; |
| if (coverage == 0) { |
| if (coverage == 0) { |
| ++spans; |
| ++spans; |
| continue; |
| continue; |
| } |
| } |
| |
| |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| DST *dest = (DST*)data->rasterBuffer->scanLine(spans->y) |
| + spans->x; |
| + spans->x; |
| |
| |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cx = spans->x + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| const qreal cy = spans->y + qreal(0.5); |
| |
| |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal x = data->m21 * cy + data->m11 * cx + data->dx; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal y = data->m22 * cy + data->m12 * cx + data->dy; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| qreal w = data->m23 * cy + data->m13 * cx + data->m33; |
| |
| |
| int length = spans->len; |
| int length = spans->len; |
| while (length) { |
| while (length) { |
| const int l = qMin(length, buffer_size); |
| const int l = qMin(length, buffer_size); |
| const SRC *end = buffer + l; |
| const SRC *end = buffer + l; |
| SRC *b = buffer; |
| SRC *b = buffer; |
| while (b < end) { |
| while (b < end) { |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal iw = w == 0 ? 1 : 1 / w; |
| const qreal tx = x * iw; |
| const qreal tx = x * iw; |
| const qreal ty = y * iw; |
| const qreal ty = y * iw; |
| |
| |
| int px = int(tx) - (tx < 0); |
| int px = int(tx) - (tx < 0); |
| int py = int(ty) - (ty < 0); |
| int py = int(ty) - (ty < 0); |
| |
| |
| |
| px %= image_width; |
| |
| py %= image_height; |
| if (px < 0) |
| if (px < 0) |
| px += image_width; |
| px += image_width; |
| if (py < 0) |
| if (py < 0) |
| py += image_height; |
| py += image_height; |
| |
| |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| *b = ((SRC*)data->texture.scanLine(py))[px]; |
| ++b; |
| ++b; |
| |
| |
| x += fdx; |
| x += fdx; |
| y += fdy; |
| y += fdy; |
| w += fdw; |
| w += fdw; |
| // force increment to avoid /0 |
| // force increment to avoid /0 |
| if (!w) |
| if (!w) |
| w += fdw; |
| w += fdw; |
| } |
| } |
| if (!SRC::hasAlpha() && coverage == 255) { |
| if (!SRC::hasAlpha() && coverage == 255) { |
| qt_memconvert(dest, buffer, l); |
| qt_memconvert(dest, buffer, l); |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) |
| { |
| { |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| blendUntransformed_dest24(dest, buffer, coverage, l); |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| (quintptr(dest) & 3) == (quintptr(buffer) & 3)) { |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| blendUntransformed_dest16(dest, buffer, coverage, l); |
| } else { |
| } else { |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| blendUntransformed_unaligned(dest, buffer, coverage, l); |
| } |
| } |
| |
| |
| dest += l; |
| dest += l; |
| length -= l; |
| length -= l; |
| } |
| } |
| ++spans; |
| ++spans; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_rgb888(int count, const QSpan *spans, |
| static void blend_transformed_tiled_rgb888(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_24) |
| #if defined(QT_QWS_DEPTH_24) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_RGB888) |
| if (data->texture.format == QImage::Format_RGB888) |
| blendTransformedTiled<qrgb888, qrgb888>(count, spans, userData); |
| blendTransformedTiled<qrgb888, qrgb888>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_argb6666(int count, const QSpan *spans, |
| static void blend_transformed_tiled_argb6666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformedTiled<qargb6666, qargb6666>(count, spans, userData); |
| blendTransformedTiled<qargb6666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformedTiled<qargb6666, qrgb666>(count, spans, userData); |
| blendTransformedTiled<qargb6666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_rgb666(int count, const QSpan *spans, |
| static void blend_transformed_tiled_rgb666(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_18) |
| #if defined(QT_QWS_DEPTH_18) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB6666_Premultiplied) |
| blendTransformedTiled<qrgb666, qargb6666>(count, spans, userData); |
| blendTransformedTiled<qrgb666, qargb6666>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB666) |
| else if (data->texture.format == QImage::Format_RGB666) |
| blendTransformedTiled<qrgb666, qrgb666>(count, spans, userData); |
| blendTransformedTiled<qrgb666, qrgb666>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, |
| static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_16) |
| #if defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformedTiled<qargb8565, qargb8565>(count, spans, userData); |
| blendTransformedTiled<qargb8565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTransformedTiled<qargb8565, qrgb565>(count, spans, userData); |
| blendTransformedTiled<qargb8565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, |
| static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| #if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) |
| blendTransformedTiled<qrgb565, qargb8565>(count, spans, userData); |
| blendTransformedTiled<qrgb565, qargb8565>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB16) |
| else if (data->texture.format == QImage::Format_RGB16) |
| blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData); |
| blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_argb8555(int count, const QSpan *spans, |
| static void blend_transformed_tiled_argb8555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformedTiled<qargb8555, qargb8555>(count, spans, userData); |
| blendTransformedTiled<qargb8555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformedTiled<qargb8555, qrgb555>(count, spans, userData); |
| blendTransformedTiled<qargb8555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_rgb555(int count, const QSpan *spans, |
| static void blend_transformed_tiled_rgb555(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_15) |
| #if defined(QT_QWS_DEPTH_15) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB8555_Premultiplied) |
| blendTransformedTiled<qrgb555, qargb8555>(count, spans, userData); |
| blendTransformedTiled<qrgb555, qargb8555>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB555) |
| else if (data->texture.format == QImage::Format_RGB555) |
| blendTransformedTiled<qrgb555, qrgb555>(count, spans, userData); |
| blendTransformedTiled<qrgb555, qrgb555>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_argb4444(int count, const QSpan *spans, |
| static void blend_transformed_tiled_argb4444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformedTiled<qargb4444, qargb4444>(count, spans, userData); |
| blendTransformedTiled<qargb4444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformedTiled<qargb4444, qrgb444>(count, spans, userData); |
| blendTransformedTiled<qargb4444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| static void blend_transformed_tiled_rgb444(int count, const QSpan *spans, |
| static void blend_transformed_tiled_rgb444(int count, const QSpan *spans, |
| void *userData) |
| void *userData) |
| { |
| { |
| #if defined(QT_QWS_DEPTH_12) |
| #if defined(QT_QWS_DEPTH_12) |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| if (data->texture.format == QImage::Format_ARGB4444_Premultiplied) |
| blendTransformedTiled<qrgb444, qargb4444>(count, spans, userData); |
| blendTransformedTiled<qrgb444, qargb4444>(count, spans, userData); |
| else if (data->texture.format == QImage::Format_RGB444) |
| else if (data->texture.format == QImage::Format_RGB444) |
| blendTransformedTiled<qrgb444, qrgb444>(count, spans, userData); |
| blendTransformedTiled<qrgb444, qrgb444>(count, spans, userData); |
| else |
| else |
| #endif |
| #endif |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| |
| |
| # define SPANFUNC_POINTER(Name, Arg) Name<Arg> |
| # define SPANFUNC_POINTER(Name, Arg) Name<Arg> |
| |
| |
| |
| |
| /* Image formats here are target formats */ |
| /* Image formats here are target formats */ |
| static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats] = { |
| static const ProcessSpans processTextureSpans[NBlendTypes][QImage::NImageFormats] = { |
| // Untransformed |
| // Untransformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_untransformed_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_untransformed_argb, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_untransformed_argb, RegularSpans), // ARGB32_Premultiplied |
| blend_untransformed_rgb565, |
| blend_untransformed_rgb565, |
| blend_untransformed_argb8565, |
| blend_untransformed_argb8565, |
| blend_untransformed_rgb666, |
| blend_untransformed_rgb666, |
| blend_untransformed_argb6666, |
| blend_untransformed_argb6666, |
| blend_untransformed_rgb555, |
| blend_untransformed_rgb555, |
| blend_untransformed_argb8555, |
| blend_untransformed_argb8555, |
| blend_untransformed_rgb888, |
| blend_untransformed_rgb888, |
| blend_untransformed_rgb444, |
| blend_untransformed_rgb444, |
| blend_untransformed_argb4444, |
| blend_untransformed_argb4444, |
| }, |
| }, |
| // Tiled |
| // Tiled |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_tiled_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_tiled_argb, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_tiled_argb, RegularSpans), // ARGB32_Premultiplied |
| blend_tiled_rgb565, |
| blend_tiled_rgb565, |
| blend_tiled_argb8565, |
| blend_tiled_argb8565, |
| blend_tiled_rgb666, |
| blend_tiled_rgb666, |
| blend_tiled_argb6666, |
| blend_tiled_argb6666, |
| blend_tiled_rgb555, |
| blend_tiled_rgb555, |
| blend_tiled_argb8555, |
| blend_tiled_argb8555, |
| blend_tiled_rgb888, |
| blend_tiled_rgb888, |
| blend_tiled_rgb444, |
| blend_tiled_rgb444, |
| blend_tiled_argb4444, |
| blend_tiled_argb4444, |
| }, |
| }, |
| // Transformed |
| // Transformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_transformed_argb, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_transformed_argb, RegularSpans), // ARGB32_Premultiplied |
| blend_transformed_rgb565, |
| blend_transformed_rgb565, |
| blend_transformed_argb8565, |
| blend_transformed_argb8565, |
| blend_transformed_rgb666, |
| blend_transformed_rgb666, |
| blend_transformed_argb6666, |
| blend_transformed_argb6666, |
| blend_transformed_rgb555, |
| blend_transformed_rgb555, |
| blend_transformed_argb8555, |
| blend_transformed_argb8555, |
| blend_transformed_rgb888, |
| blend_transformed_rgb888, |
| blend_transformed_rgb444, |
| blend_transformed_rgb444, |
| blend_transformed_argb4444, |
| blend_transformed_argb4444, |
| }, |
| }, |
| // TransformedTiled |
| // TransformedTiled |
| { |
| { |
| 0, |
| 0, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_transformed_tiled_argb, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_transformed_tiled_argb, RegularSpans), // ARGB32_Premultiplied |
| blend_transformed_tiled_rgb565, |
| blend_transformed_tiled_rgb565, |
| blend_transformed_tiled_argb8565, |
| blend_transformed_tiled_argb8565, |
| blend_transformed_tiled_rgb666, |
| blend_transformed_tiled_rgb666, |
| blend_transformed_tiled_argb6666, |
| blend_transformed_tiled_argb6666, |
| blend_transformed_tiled_rgb555, |
| blend_transformed_tiled_rgb555, |
| blend_transformed_tiled_argb8555, |
| blend_transformed_tiled_argb8555, |
| blend_transformed_tiled_rgb888, |
| blend_transformed_tiled_rgb888, |
| blend_transformed_tiled_rgb444, |
| blend_transformed_tiled_rgb444, |
| blend_transformed_tiled_argb4444 |
| blend_transformed_tiled_argb4444 |
| }, |
| }, |
| // Bilinear |
| // Bilinear |
| { |
| { |
| 0, |
| 0, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied |
| blend_transformed_bilinear_rgb565, |
| blend_transformed_bilinear_rgb565, |
| blend_transformed_bilinear_argb8565, |
| blend_transformed_bilinear_argb8565, |
| blend_transformed_bilinear_rgb666, |
| blend_transformed_bilinear_rgb666, |
| blend_transformed_bilinear_argb6666, |
| blend_transformed_bilinear_argb6666, |
| blend_transformed_bilinear_rgb555, |
| blend_transformed_bilinear_rgb555, |
| blend_transformed_bilinear_argb8555, |
| blend_transformed_bilinear_argb8555, |
| blend_transformed_bilinear_rgb888, |
| blend_transformed_bilinear_rgb888, |
| blend_transformed_bilinear_rgb444, |
| blend_transformed_bilinear_rgb444, |
| blend_transformed_bilinear_argb4444, |
| blend_transformed_bilinear_argb4444, |
| }, |
| }, |
| // BilinearTiled |
| // BilinearTiled |
| { |
| { |
| 0, |
| 0, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Mono |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // MonoLsb |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // Indexed8 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB32_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB16 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8565_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB666 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB6666_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB6666_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB555 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB555 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8555_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB8555_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB888 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB888 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB444 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // RGB444 |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB4444_Premultiplied |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), // ARGB4444_Premultiplied |
| } |
| } |
| }; |
| }; |
| |
| |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImageFormats] = { |
| static const ProcessSpans processTextureSpansCallback[NBlendTypes][QImage::NImageFormats] = { |
| // Untransformed |
| // Untransformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| blend_untransformed_generic<CallbackSpans>, // Mono |
| blend_untransformed_generic<CallbackSpans>, // Mono |
| blend_untransformed_generic<CallbackSpans>, // MonoLsb |
| blend_untransformed_generic<CallbackSpans>, // MonoLsb |
| blend_untransformed_generic<CallbackSpans>, // Indexed8 |
| blend_untransformed_generic<CallbackSpans>, // Indexed8 |
| blend_untransformed_generic<CallbackSpans>, // RGB32 |
| blend_untransformed_generic<CallbackSpans>, // RGB32 |
| blend_untransformed_generic<CallbackSpans>, // ARGB32 |
| blend_untransformed_generic<CallbackSpans>, // ARGB32 |
| blend_untransformed_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_untransformed_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // RGB16 |
| blend_untransformed_generic<CallbackSpans>, // RGB16 |
| blend_untransformed_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // RGB666 |
| blend_untransformed_generic<CallbackSpans>, // RGB666 |
| blend_untransformed_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // RGB555 |
| blend_untransformed_generic<CallbackSpans>, // RGB555 |
| blend_untransformed_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_untransformed_generic<CallbackSpans>, // RGB888 |
| blend_untransformed_generic<CallbackSpans>, // RGB888 |
| blend_untransformed_generic<CallbackSpans>, // RGB444 |
| blend_untransformed_generic<CallbackSpans>, // RGB444 |
| blend_untransformed_generic<CallbackSpans> // ARGB4444_Premultiplied |
| blend_untransformed_generic<CallbackSpans> // ARGB4444_Premultiplied |
| }, |
| }, |
| // Tiled |
| // Tiled |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| blend_tiled_generic<CallbackSpans>, // Mono |
| blend_tiled_generic<CallbackSpans>, // Mono |
| blend_tiled_generic<CallbackSpans>, // MonoLsb |
| blend_tiled_generic<CallbackSpans>, // MonoLsb |
| blend_tiled_generic<CallbackSpans>, // Indexed8 |
| blend_tiled_generic<CallbackSpans>, // Indexed8 |
| blend_tiled_generic<CallbackSpans>, // RGB32 |
| blend_tiled_generic<CallbackSpans>, // RGB32 |
| blend_tiled_generic<CallbackSpans>, // ARGB32 |
| blend_tiled_generic<CallbackSpans>, // ARGB32 |
| blend_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // RGB16 |
| blend_tiled_generic<CallbackSpans>, // RGB16 |
| blend_tiled_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // RGB666 |
| blend_tiled_generic<CallbackSpans>, // RGB666 |
| blend_tiled_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // RGB555 |
| blend_tiled_generic<CallbackSpans>, // RGB555 |
| blend_tiled_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_tiled_generic<CallbackSpans>, // RGB888 |
| blend_tiled_generic<CallbackSpans>, // RGB888 |
| blend_tiled_generic<CallbackSpans>, // RGB444 |
| blend_tiled_generic<CallbackSpans>, // RGB444 |
| blend_tiled_generic<CallbackSpans> // ARGB4444_Premultiplied |
| blend_tiled_generic<CallbackSpans> // ARGB4444_Premultiplied |
| }, |
| }, |
| // Transformed |
| // Transformed |
| { |
| { |
| 0, // Invalid |
| 0, // Invalid |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_transformed_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_transformed_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans>, // ARGB4444_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB4444_Premultiplied |
| }, |
| }, |
| // TransformedTiled |
| // TransformedTiled |
| { |
| { |
| 0, |
| 0, |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_transformed_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_transformed_tiled_argb<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| }, |
| }, |
| // Bilinear |
| // Bilinear |
| { |
| { |
| 0, |
| 0, |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| }, |
| }, |
| // BilinearTiled |
| // BilinearTiled |
| { |
| { |
| 0, |
| 0, |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // Mono |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // MonoLsb |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // Indexed8 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // RGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32 |
| blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB32_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // RGB16 |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8565_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // RGB666 |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB6666_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // RGB555 |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // ARGB8555_Premultiplied |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB888 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans>, // RGB444 |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| blend_src_generic<CallbackSpans> // ARGB4444_Premultiplied |
| } |
| } |
| }; |
| }; |
| #endif // QT_NO_RASTERCALLBACKS |
| #endif // QT_NO_RASTERCALLBACKS |
| |
| |
| void qBlendTexture(int count, const QSpan *spans, void *userData) |
| void qBlendTexture(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| ProcessSpans proc = processTextureSpans[getBlendType(data)][data->rasterBuffer->format]; |
| ProcessSpans proc = processTextureSpans[getBlendType(data)][data->rasterBuffer->format]; |
| proc(count, spans, userData); |
| proc(count, spans, userData); |
| } |
| } |
| |
| |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| void qBlendTextureCallback(int count, const QSpan *spans, void *userData) |
| void qBlendTextureCallback(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| ProcessSpans proc = processTextureSpansCallback[getBlendType(data)][data->rasterBuffer->format]; |
| ProcessSpans proc = processTextureSpansCallback[getBlendType(data)][data->rasterBuffer->format]; |
| proc(count, spans, userData); |
| proc(count, spans, userData); |
| } |
| } |
| #endif // QT_NO_RASTERCALLBACKS |
| #endif // QT_NO_RASTERCALLBACKS |
| |
| |
| template <class DST> |
| template <class DST> |
| inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, |
| inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uchar *map, |
| const uchar *map, |
| int mapWidth, int mapHeight, int mapStride, |
| int mapWidth, int mapHeight, int mapStride, |
| DST dummy = 0) |
| DST dummy = 0) |
| { |
| { |
| Q_UNUSED(dummy); |
| Q_UNUSED(dummy); |
| const DST c = qt_colorConvert<DST, quint32>(color, 0); |
| 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); |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(DST); |
| |
| |
| if (mapWidth > 8) { |
| if (mapWidth > 8) { |
| while (mapHeight--) { |
| while (mapHeight--) { |
| int x0 = 0; |
| int x0 = 0; |
| int n = 0; |
| int n = 0; |
| for (int x = 0; x < mapWidth; x += 8) { |
| for (int x = 0; x < mapWidth; x += 8) { |
| uchar s = map[x >> 3]; |
| uchar s = map[x >> 3]; |
| for (int i = 0; i < 8; ++i) { |
| for (int i = 0; i < 8; ++i) { |
| if (s & 0x80) { |
| if (s & 0x80) { |
| ++n; |
| ++n; |
| } else { |
| } else { |
| if (n) { |
| if (n) { |
| qt_memfill(dest + x0, c, n); |
| qt_memfill(dest + x0, c, n); |
| x0 += n + 1; |
| x0 += n + 1; |
| n = 0; |
| n = 0; |
| } else { |
| } else { |
| ++x0; |
| ++x0; |
| } |
| } |
| if (!s) { |
| if (!s) { |
| x0 += 8 - 1 - i; |
| x0 += 8 - 1 - i; |
| break; |
| break; |
| } |
| } |
| } |
| } |
| s <<= 1; |
| s <<= 1; |
| } |
| } |
| } |
| } |
| if (n) |
| if (n) |
| qt_memfill(dest + x0, c, n); |
| qt_memfill(dest + x0, c, n); |
| dest += destStride; |
| dest += destStride; |
| map += mapStride; |
| map += mapStride; |
| } |
| } |
| } else { |
| } else { |
| while (mapHeight--) { |
| while (mapHeight--) { |
| int x0 = 0; |
| int x0 = 0; |
| int n = 0; |
| int n = 0; |
| for (uchar s = *map; s; s <<= 1) { |
| for (uchar s = *map; s; s <<= 1) { |
| if (s & 0x80) { |
| if (s & 0x80) { |
| ++n; |
| ++n; |
| } else if (n) { |
| } else if (n) { |
| qt_memfill(dest + x0, c, n); |
| qt_memfill(dest + x0, c, n); |
| x0 += n + 1; |
| x0 += n + 1; |
| n = 0; |
| n = 0; |
| } else { |
| } else { |
| ++x0; |
| ++x0; |
| } |
| } |
| } |
| } |
| if (n) |
| if (n) |
| qt_memfill(dest + x0, c, n); |
| qt_memfill(dest + x0, c, n); |
| dest += destStride; |
| dest += destStride; |
| map += mapStride; |
| map += mapStride; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void qt_gradient_quint32(int count, const QSpan *spans, void *userData) |
| static void qt_gradient_quint32(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| bool isVerticalGradient = |
| bool isVerticalGradient = |
| data->txop <= QTransform::TxScale && |
| data->txop <= QTransform::TxScale && |
| data->type == QSpanData::LinearGradient && |
| data->type == QSpanData::LinearGradient && |
| data->gradient.linear.end.x == data->gradient.linear.origin.x; |
| data->gradient.linear.end.x == data->gradient.linear.origin.x; |
| |
| |
| if (isVerticalGradient) { |
| if (isVerticalGradient) { |
| LinearGradientValues linear; |
| LinearGradientValues linear; |
| getLinearGradientValues(&linear, data); |
| getLinearGradientValues(&linear, data); |
| |
| |
| CompositionFunctionSolid funcSolid = |
| CompositionFunctionSolid funcSolid = |
| functionForModeSolid[data->rasterBuffer->compositionMode]; |
| functionForModeSolid[data->rasterBuffer->compositionMode]; |
| |
| |
| /* |
| /* |
| The logic for vertical gradient calculations is a mathematically |
| The logic for vertical gradient calculations is a mathematically |
| reduced copy of that in fetchLinearGradient() - which is basically: |
| reduced copy of that in fetchLinearGradient() - which is basically: |
| |
| |
| qreal ry = data->m22 * (y + 0.5) + data->dy; |
| qreal ry = data->m22 * (y + 0.5) + data->dy; |
| qreal t = linear.dy*ry + linear.off; |
| qreal t = linear.dy*ry + linear.off; |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| quint32 color = |
| quint32 color = |
| qt_gradient_pixel_fixed(&data->gradient, |
| qt_gradient_pixel_fixed(&data->gradient, |
| int(t * FIXPT_SIZE)); |
| int(t * FIXPT_SIZE)); |
| |
| |
| This has then been converted to fixed point to improve performance. |
| This has then been converted to fixed point to improve performance. |
| */ |
| */ |
| const int gss = GRADIENT_STOPTABLE_SIZE - 1; |
| const int gss = GRADIENT_STOPTABLE_SIZE - 1; |
| int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); |
| int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); |
| int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE)); |
| int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE)); |
| |
| |
| while (count--) { |
| while (count--) { |
| int y = spans->y; |
| int y = spans->y; |
| int x = spans->x; |
| int x = spans->x; |
| |
| |
| quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x; |
| quint32 *dst = (quint32 *)(data->rasterBuffer->scanLine(y)) + x; |
| quint32 color = |
| quint32 color = |
| qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); |
| qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); |
| |
| |
| funcSolid(dst, spans->len, color, spans->coverage); |
| funcSolid(dst, spans->len, color, spans->coverage); |
| ++spans; |
| ++spans; |
| } |
| } |
| |
| |
| } else { |
| } else { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| } |
| } |
| |
| |
| static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) |
| static void qt_gradient_quint16(int count, const QSpan *spans, void *userData) |
| { |
| { |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| bool isVerticalGradient = |
| bool isVerticalGradient = |
| data->txop <= QTransform::TxScale && |
| data->txop <= QTransform::TxScale && |
| data->type == QSpanData::LinearGradient && |
| data->type == QSpanData::LinearGradient && |
| data->gradient.linear.end.x == data->gradient.linear.origin.x; |
| data->gradient.linear.end.x == data->gradient.linear.origin.x; |
| |
| |
| if (isVerticalGradient) { |
| if (isVerticalGradient) { |
| |
| |
| LinearGradientValues linear; |
| LinearGradientValues linear; |
| getLinearGradientValues(&linear, data); |
| getLinearGradientValues(&linear, data); |
| |
| |
| /* |
| /* |
| The logic for vertical gradient calculations is a mathematically |
| The logic for vertical gradient calculations is a mathematically |
| reduced copy of that in fetchLinearGradient() - which is basically: |
| reduced copy of that in fetchLinearGradient() - which is basically: |
| |
| |
| qreal ry = data->m22 * (y + 0.5) + data->dy; |
| qreal ry = data->m22 * (y + 0.5) + data->dy; |
| qreal t = linear.dy*ry + linear.off; |
| qreal t = linear.dy*ry + linear.off; |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| t *= (GRADIENT_STOPTABLE_SIZE - 1); |
| quint32 color = |
| quint32 color = |
| qt_gradient_pixel_fixed(&data->gradient, |
| qt_gradient_pixel_fixed(&data->gradient, |
| int(t * FIXPT_SIZE)); |
| int(t * FIXPT_SIZE)); |
| |
| |
| This has then been converted to fixed point to improve performance. |
| This has then been converted to fixed point to improve performance. |
| */ |
| */ |
| const int gss = GRADIENT_STOPTABLE_SIZE - 1; |
| const int gss = GRADIENT_STOPTABLE_SIZE - 1; |
| int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); |
| int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); |
| int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE)); |
| int off = int((((linear.dy * (data->m22 * 0.5 + data->dy) + linear.off) * gss) * FIXPT_SIZE)); |
| |
| |
| uint oldColor = data->solid.color; |
| uint oldColor = data->solid.color; |
| while (count--) { |
| while (count--) { |
| int y = spans->y; |
| int y = spans->y; |
| |
| |
| quint32 color = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); |
| quint32 color = qt_gradient_pixel_fixed(&data->gradient, yinc * y + off); |
| |
| |
| data->solid.color = color; |
| data->solid.color = color; |
| blend_color_rgb16(1, spans, userData); |
| blend_color_rgb16(1, spans, userData); |
| ++spans; |
| ++spans; |
| } |
| } |
| data->solid.color = oldColor; |
| data->solid.color = oldColor; |
| |
| |
| } else { |
| } else { |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| blend_src_generic<RegularSpans>(count, spans, userData); |
| } |
| } |
| } |
| } |
| |
| |
| inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, |
| inline static void qt_bitmapblit_quint32(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uchar *map, |
| const uchar *map, |
| int mapWidth, int mapHeight, int mapStride) |
| int mapWidth, int mapHeight, int mapStride) |
| { |
| { |
| qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color, |
| qt_bitmapblit_template<quint32>(rasterBuffer, x, y, color, |
| map, mapWidth, mapHeight, mapStride); |
| map, mapWidth, mapHeight, mapStride); |
| } |
| } |
| |
| |
| inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, |
| inline static void qt_bitmapblit_quint16(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uchar *map, |
| const uchar *map, |
| int mapWidth, int mapHeight, int mapStride) |
| int mapWidth, int mapHeight, int mapStride) |
| { |
| { |
| qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color, |
| qt_bitmapblit_template<quint16>(rasterBuffer, x, y, color, |
| map, mapWidth, mapHeight, mapStride); |
| map, mapWidth, mapHeight, mapStride); |
| } |
| } |
| |
| |
| |
| |
| uchar qt_pow_rgb_gamma[256]; |
| uchar qt_pow_rgb_gamma[256]; |
| uchar qt_pow_rgb_invgamma[256]; |
| uchar qt_pow_rgb_invgamma[256]; |
| |
| |
| uint qt_pow_gamma[256]; |
| uint qt_pow_gamma[256]; |
| uchar qt_pow_invgamma[2048]; |
| uchar qt_pow_invgamma[2048]; |
| |
| |
| static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, |
| static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uchar *map, |
| const uchar *map, |
| int mapWidth, int mapHeight, int mapStride, |
| int mapWidth, int mapHeight, int mapStride, |
| const QClipData *) |
| const QClipData *) |
| { |
| { |
| const quint16 c = qt_colorConvert<quint16, quint32>(color, 0); |
| const quint16 c = qt_colorConvert<quint16, quint32>(color, 0); |
| quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; |
| quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x; |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16); |
| |
| |
| while (mapHeight--) { |
| while (mapHeight--) { |
| for (int i = 0; i < mapWidth; ++i) { |
| for (int i = 0; i < mapWidth; ++i) { |
| const int coverage = map[i]; |
| const int coverage = map[i]; |
| |
| |
| if (coverage == 0) { |
| if (coverage == 0) { |
| // nothing |
| // nothing |
| } else if (coverage == 255) { |
| } else if (coverage == 255) { |
| dest[i] = c; |
| dest[i] = c; |
| } else { |
| } else { |
| int ialpha = 255 - coverage; |
| int ialpha = 255 - coverage; |
| dest[i] = BYTE_MUL_RGB16(c, coverage) |
| dest[i] = BYTE_MUL_RGB16(c, coverage) |
| + BYTE_MUL_RGB16(dest[i], ialpha); |
| + BYTE_MUL_RGB16(dest[i], ialpha); |
| } |
| } |
| } |
| } |
| dest += destStride; |
| dest += destStride; |
| map += mapStride; |
| map += mapStride; |
| } |
| } |
| } |
| } |
| |
| |
| void qt_build_pow_tables() { |
| void qt_build_pow_tables() { |
| qreal smoothing = qreal(1.7); |
| qreal smoothing = qreal(1.7); |
| |
| |
| #ifdef Q_WS_MAC |
| #ifdef Q_WS_MAC |
| // decided by testing a few things on an iMac, should probably get this from the |
| // decided by testing a few things on an iMac, should probably get this from the |
| // system... |
| // system... |
| smoothing = 2.0; |
| smoothing = 2.0; |
| #endif |
| #endif |
| |
| |
| #ifdef Q_WS_WIN |
| #ifdef Q_WS_WIN |
| int winSmooth; |
| int winSmooth; |
| if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) |
| if (SystemParametersInfo(0x200C /* SPI_GETFONTSMOOTHINGCONTRAST */, 0, &winSmooth, 0)) |
| smoothing = winSmooth / 1000.0; |
| smoothing = winSmooth / 1000.0; |
| |
| |
| // Safeguard ourselves against corrupt registry values... |
| // Safeguard ourselves against corrupt registry values... |
| if (smoothing > 5 || smoothing < 1) |
| if (smoothing > 5 || smoothing < 1) |
| smoothing = 1.4; |
| smoothing = 1.4; |
| |
| |
| #endif |
| #endif |
| |
| |
| #ifdef Q_WS_X11 |
| #ifdef Q_WS_X11 |
| Q_UNUSED(smoothing); |
| Q_UNUSED(smoothing); |
| for (int i=0; i<256; ++i) { |
| for (int i=0; i<256; ++i) { |
| qt_pow_rgb_gamma[i] = uchar(i); |
| qt_pow_rgb_gamma[i] = uchar(i); |
| qt_pow_rgb_invgamma[i] = uchar(i); |
| qt_pow_rgb_invgamma[i] = uchar(i); |
| } |
| } |
| #else |
| #else |
| for (int i=0; i<256; ++i) { |
| for (int i=0; i<256; ++i) { |
| qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255)); |
| qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255)); |
| qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255)); |
| qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255)); |
| } |
| } |
| #endif |
| #endif |
| |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| const qreal gray_gamma = 2.31; |
| const qreal gray_gamma = 2.31; |
| for (int i=0; i<256; ++i) |
| for (int i=0; i<256; ++i) |
| qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); |
| qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); |
| for (int i=0; i<2048; ++i) |
| for (int i=0; i<2048; ++i) |
| qt_pow_invgamma[i] = uchar(qRound(qPow(i / 2047.0, 1 / gray_gamma) * 255)); |
| qt_pow_invgamma[i] = uchar(qRound(qPow(i / 2047.0, 1 / gray_gamma) * 255)); |
| #endif |
| #endif |
| } |
| } |
| |
| |
| static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
| static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
| { |
| { |
| // Do a gray alphablend... |
| // Do a gray alphablend... |
| int da = qAlpha(*dst); |
| int da = qAlpha(*dst); |
| int dr = qRed(*dst); |
| int dr = qRed(*dst); |
| int dg = qGreen(*dst); |
| int dg = qGreen(*dst); |
| int db = qBlue(*dst); |
| int db = qBlue(*dst); |
| |
| |
| if (da != 255 |
| if (da != 255 |
| #if defined (Q_WS_WIN) |
| #if defined (Q_WS_WIN) |
| // Work around GDI messing up alpha channel |
| // Work around GDI messing up alpha channel |
| && qRed(*dst) <= da && qBlue(*dst) <= da && qGreen(*dst) <= da |
| && qRed(*dst) <= da && qBlue(*dst) <= da && qGreen(*dst) <= da |
| #endif |
| #endif |
| ) { |
| ) { |
| |
| |
| int a = qGray(coverage); |
| int a = qGray(coverage); |
| sr = qt_div_255(qt_pow_rgb_invgamma[sr] * a); |
| sr = qt_div_255(qt_pow_rgb_invgamma[sr] * a); |
| sg = qt_div_255(qt_pow_rgb_invgamma[sg] * a); |
| sg = qt_div_255(qt_pow_rgb_invgamma[sg] * a); |
| sb = qt_div_255(qt_pow_rgb_invgamma[sb] * a); |
| sb = qt_div_255(qt_pow_rgb_invgamma[sb] * a); |
| |
| |
| int ia = 255 - a; |
| int ia = 255 - a; |
| dr = qt_div_255(dr * ia); |
| dr = qt_div_255(dr * ia); |
| dg = qt_div_255(dg * ia); |
| dg = qt_div_255(dg * ia); |
| db = qt_div_255(db * ia); |
| db = qt_div_255(db * ia); |
| |
| |
| *dst = ((a + qt_div_255((255 - a) * da)) << 24) |
| *dst = ((a + qt_div_255((255 - a) * da)) << 24) |
| | ((sr + dr) << 16) |
| | ((sr + dr) << 16) |
| | ((sg + dg) << 8) |
| | ((sg + dg) << 8) |
| | ((sb + db)); |
| | ((sb + db)); |
| return; |
| return; |
| } |
| } |
| |
| |
| int mr = qRed(coverage); |
| int mr = qRed(coverage); |
| int mg = qGreen(coverage); |
| int mg = qGreen(coverage); |
| int mb = qBlue(coverage); |
| int mb = qBlue(coverage); |
| |
| |
| dr = qt_pow_rgb_gamma[dr]; |
| dr = qt_pow_rgb_gamma[dr]; |
| dg = qt_pow_rgb_gamma[dg]; |
| dg = qt_pow_rgb_gamma[dg]; |
| db = qt_pow_rgb_gamma[db]; |
| db = qt_pow_rgb_gamma[db]; |
| |
| |
| int nr = qt_div_255((sr - dr) * mr) + dr; |
| int nr = qt_div_255((sr - dr) * mr) + dr; |
| int ng = qt_div_255((sg - dg) * mg) + dg; |
| int ng = qt_div_255((sg - dg) * mg) + dg; |
| int nb = qt_div_255((sb - db) * mb) + db; |
| int nb = qt_div_255((sb - db) * mb) + db; |
| |
| |
| nr = qt_pow_rgb_invgamma[nr]; |
| nr = qt_pow_rgb_invgamma[nr]; |
| ng = qt_pow_rgb_invgamma[ng]; |
| ng = qt_pow_rgb_invgamma[ng]; |
| nb = qt_pow_rgb_invgamma[nb]; |
| nb = qt_pow_rgb_invgamma[nb]; |
| |
| |
| *dst = qRgb(nr, ng, nb); |
| *dst = qRgb(nr, ng, nb); |
| } |
| } |
| |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
| static inline void grayBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
| { |
| { |
| // Do a gammacorrected gray alphablend... |
| // Do a gammacorrected gray alphablend... |
| int dr = qRed(*dst); |
| int dr = qRed(*dst); |
| int dg = qGreen(*dst); |
| int dg = qGreen(*dst); |
| int db = qBlue(*dst); |
| int db = qBlue(*dst); |
| |
| |
| dr = qt_pow_gamma[dr]; |
| dr = qt_pow_gamma[dr]; |
| dg = qt_pow_gamma[dg]; |
| dg = qt_pow_gamma[dg]; |
| db = qt_pow_gamma[db]; |
| db = qt_pow_gamma[db]; |
| |
| |
| int alpha = coverage; |
| int alpha = coverage; |
| int ialpha = 255 - alpha; |
| int ialpha = 255 - alpha; |
| int nr = (sr * alpha + ialpha * dr) / 255; |
| int nr = (sr * alpha + ialpha * dr) / 255; |
| int ng = (sg * alpha + ialpha * dg) / 255; |
| int ng = (sg * alpha + ialpha * dg) / 255; |
| int nb = (sb * alpha + ialpha * db) / 255; |
| int nb = (sb * alpha + ialpha * db) / 255; |
| |
| |
| nr = qt_pow_invgamma[nr]; |
| nr = qt_pow_invgamma[nr]; |
| ng = qt_pow_invgamma[ng]; |
| ng = qt_pow_invgamma[ng]; |
| nb = qt_pow_invgamma[nb]; |
| nb = qt_pow_invgamma[nb]; |
| |
| |
| *dst = qRgb(nr, ng, nb); |
| *dst = qRgb(nr, ng, nb); |
| } |
| } |
| #endif |
| #endif |
| |
| |
| static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, |
| static void qt_alphamapblit_quint32(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uchar *map, |
| const uchar *map, |
| int mapWidth, int mapHeight, int mapStride, |
| int mapWidth, int mapHeight, int mapStride, |
| const QClipData *clip) |
| const QClipData *clip) |
| { |
| { |
| const quint32 c = color; |
| const quint32 c = color; |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); |
| |
| |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| |
| |
| sr = qt_pow_gamma[sr]; |
| sr = qt_pow_gamma[sr]; |
| sg = qt_pow_gamma[sg]; |
| sg = qt_pow_gamma[sg]; |
| sb = qt_pow_gamma[sb]; |
| sb = qt_pow_gamma[sb]; |
| bool opaque_src = (qAlpha(color) == 255); |
| bool opaque_src = (qAlpha(color) == 255); |
| #endif |
| #endif |
| |
| |
| if (!clip) { |
| if (!clip) { |
| quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; |
| quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; |
| while (mapHeight--) { |
| while (mapHeight--) { |
| for (int i = 0; i < mapWidth; ++i) { |
| for (int i = 0; i < mapWidth; ++i) { |
| const int coverage = map[i]; |
| const int coverage = map[i]; |
| |
| |
| if (coverage == 0) { |
| if (coverage == 0) { |
| // nothing |
| // nothing |
| } else if (coverage == 255) { |
| } else if (coverage == 255) { |
| dest[i] = c; |
| dest[i] = c; |
| } else { |
| } else { |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src |
| if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src |
| && qAlpha(dest[i]) == 255) { |
| && qAlpha(dest[i]) == 255) { |
| grayBlendPixel(dest+i, coverage, sr, sg, sb); |
| grayBlendPixel(dest+i, coverage, sr, sg, sb); |
| } else |
| } else |
| #endif |
| #endif |
| { |
| { |
| int ialpha = 255 - coverage; |
| int ialpha = 255 - coverage; |
| dest[i] = INTERPOLATE_PIXEL_255(c, coverage, dest[i], ialpha); |
| dest[i] = INTERPOLATE_PIXEL_255(c, coverage, dest[i], ialpha); |
| } |
| } |
| } |
| } |
| } |
| } |
| dest += destStride; |
| dest += destStride; |
| map += mapStride; |
| map += mapStride; |
| } |
| } |
| } else { |
| } else { |
| int bottom = qMin(y + mapHeight, rasterBuffer->height()); |
| int bottom = qMin(y + mapHeight, rasterBuffer->height()); |
| |
| |
| int top = qMax(y, 0); |
| int top = qMax(y, 0); |
| map += (top - y) * mapStride; |
| map += (top - y) * mapStride; |
| |
| |
| const_cast<QClipData *>(clip)->initialize(); |
| const_cast<QClipData *>(clip)->initialize(); |
| for (int yp = top; yp<bottom; ++yp) { |
| for (int yp = top; yp<bottom; ++yp) { |
| const QClipData::ClipLine &line = clip->m_clipLines[yp]; |
| const QClipData::ClipLine &line = clip->m_clipLines[yp]; |
| |
| |
| quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp)); |
| quint32 *dest = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp)); |
| |
| |
| for (int i=0; i<line.count; ++i) { |
| for (int i=0; i<line.count; ++i) { |
| const QSpan &clip = line.spans[i]; |
| const QSpan &clip = line.spans[i]; |
| |
| |
| int start = qMax<int>(x, clip.x); |
| int start = qMax<int>(x, clip.x); |
| int end = qMin<int>(x + mapWidth, clip.x + clip.len); |
| int end = qMin<int>(x + mapWidth, clip.x + clip.len); |
| |
| |
| for (int xp=start; xp<end; ++xp) { |
| for (int xp=start; xp<end; ++xp) { |
| const int coverage = map[xp - x]; |
| const int coverage = map[xp - x]; |
| |
| |
| if (coverage == 0) { |
| if (coverage == 0) { |
| // nothing |
| // nothing |
| } else if (coverage == 255) { |
| } else if (coverage == 255) { |
| dest[xp] = c; |
| dest[xp] = c; |
| } else { |
| } else { |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
| if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src |
| if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && opaque_src |
| && qAlpha(dest[xp]) == 255) { |
| && qAlpha(dest[xp]) == 255) { |
| grayBlendPixel(dest+xp, coverage, sr, sg, sb); |
| grayBlendPixel(dest+xp, coverage, sr, sg, sb); |
| } else |
| } else |
| #endif |
| #endif |
| { |
| { |
| int ialpha = 255 - coverage; |
| int ialpha = 255 - coverage; |
| dest[xp] = INTERPOLATE_PIXEL_255(c, coverage, dest[xp], ialpha); |
| dest[xp] = INTERPOLATE_PIXEL_255(c, coverage, dest[xp], ialpha); |
| } |
| } |
| } |
| } |
| |
| |
| } // for (i -> line.count) |
| } // for (i -> line.count) |
| } // for (yp -> bottom) |
| } // for (yp -> bottom) |
| map += mapStride; |
| map += mapStride; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, |
| static void qt_alphargbblit_quint32(QRasterBuffer *rasterBuffer, |
| int x, int y, quint32 color, |
| int x, int y, quint32 color, |
| const uint *src, int mapWidth, int mapHeight, int srcStride, |
| const uint *src, int mapWidth, int mapHeight, int srcStride, |
| const QClipData *clip) |
| const QClipData *clip) |
| { |
| { |
| const quint32 c = color; |
| const quint32 c = color; |
| |
| |
| int sr = qRed(color); |
| int sr = qRed(color); |
| int sg = qGreen(color); |
| int sg = qGreen(color); |
| int sb = qBlue(color); |
| int sb = qBlue(color); |
| int sa = qAlpha(color); |
| int sa = qAlpha(color); |
| |
| |
| sr = qt_pow_rgb_gamma[sr]; |
| sr = qt_pow_rgb_gamma[sr]; |
| sg = qt_pow_rgb_gamma[sg]; |
| sg = qt_pow_rgb_gamma[sg]; |
| sb = qt_pow_rgb_gamma[sb]; |
| sb = qt_pow_rgb_gamma[sb]; |
| |
| |
| if (sa == 0) |
| if (sa == 0) |
| return; |
| return; |
| |
| |
| if (!clip) { |
| if (!clip) { |
| quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; |
| quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x; |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); |
| const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32); |
| while (mapHeight--) { |
| while (mapHeight--) { |
| for (int i = 0; i < mapWidth; ++i) { |
| for (int i = 0; i < mapWidth; ++i) { |
| const uint coverage = src[i]; |
| const uint coverage = src[i]; |
| if (coverage == 0xffffffff) { |
| if (coverage == 0xffffffff) { |
| dst[i] = c; |
| dst[i] = c; |
| } else if (coverage != 0xff000000) { |
| } else if (coverage != 0xff000000) { |
| rgbBlendPixel(dst+i, coverage, sr, sg, sb); |
| rgbBlendPixel(dst+i, coverage, sr, sg, sb); |
| } |
| } |
| } |
| } |
| |
| |
| dst += destStride; |
| dst += destStride; |
| src += srcStride; |
| src += srcStride; |
| } |
| } |
| } else { |
| } else { |
| int bottom = qMin(y + mapHeight, rasterBuffer->height()); |
| int bottom = qMin(y + mapHeight, rasterBuffer->height()); |
| |
| |
| int top = qMax(y, 0); |
| int top = qMax(y, 0); |
| src += (top - y) * srcStride; |
| src += (top - y) * srcStride; |
| |
| |
| const_cast<QClipData *>(clip)->initialize(); |
| const_cast<QClipData *>(clip)->initialize(); |
| for (int yp = top; yp<bottom; ++yp) { |
| for (int yp = top; yp<bottom; ++yp) { |
| const QClipData::ClipLine &line = clip->m_clipLines[yp]; |
| const QClipData::ClipLine &line = clip->m_clipLines[yp]; |
| |
| |
| quint32 *dst = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp)); |
| quint32 *dst = reinterpret_cast<quint32 *>(rasterBuffer->scanLine(yp)); |
| |
| |
| for (int i=0; i<line.count; ++i) { |
| for (int i=0; i<line.count; ++i) { |
| const QSpan &clip = line.spans[i]; |
| const QSpan &clip = line.spans[i]; |
| |
| |
| int start = qMax<int>(x, clip.x); |
| int start = qMax<int>(x, clip.x); |
| int end = qMin<int>(x + mapWidth, clip.x + clip.len); |
| int end = qMin<int>(x + mapWidth, clip.x + clip.len); |
| |
| |
| for (int xp=start; xp<end; ++xp) { |
| for (int xp=start; xp<end; ++xp) { |
| const uint coverage = src[xp - x]; |
| const uint coverage = src[xp - x]; |
| if (coverage == 0xffffffff) { |
| if (coverage == 0xffffffff) { |
| dst[xp] = c; |
| dst[xp] = c; |
| } else if (coverage != 0xff000000) { |
| } else if (coverage != 0xff000000) { |
| rgbBlendPixel(dst+xp, coverage, sr, sg, sb); |
| rgbBlendPixel(dst+xp, coverage, sr, sg, sb); |
| } |
| } |
| } |
| } |
| } // for (i -> line.count) |
| } // for (i -> line.count) |
| src += srcStride; |
| src += srcStride; |
| } // for (yp -> bottom) |
| } // for (yp -> bottom) |
| |
| |
| } |
| } |
| } |
| } |
| |
| |
| template <class T> |
| template <class T> |
| inline void qt_rectfill_template(QRasterBuffer *rasterBuffer, |
| inline void qt_rectfill_template(QRasterBuffer *rasterBuffer, |
| int x, int y, int width, int height, |
| int x, int y, int width, int height, |
| quint32 color, T dummy = 0) |
| quint32 color, T dummy = 0) |
| { |
| { |
| Q_UNUSED(dummy); |
| Q_UNUSED(dummy); |
| |
| |
| qt_rectfill<T>(reinterpret_cast<T*>(rasterBuffer->buffer()), |
| qt_rectfill<T>(reinterpret_cast<T*>(rasterBuffer->buffer()), |
| qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0), |
| qt_colorConvert<T, quint32p>(quint32p::fromRawData(color), 0), |
| x, y, width, height, rasterBuffer->bytesPerLine()); |
| x, y, width, height, rasterBuffer->bytesPerLine()); |
| } |
| } |
| |
| |
| #define QT_RECTFILL(T) \ |
| #define QT_RECTFILL(T) \ |
| inline static void qt_rectfill_##T(QRasterBuffer *rasterBuffer, \ |
| inline static void qt_rectfill_##T(QRasterBuffer *rasterBuffer, \ |
| int x, int y, int width, int height, \ |
| int x, int y, int width, int height, \ |
| quint32 color) \ |
| quint32 color) \ |
| { \ |
| { \ |
| qt_rectfill_template<T>(rasterBuffer, x, y, width, height, color); \ |
| qt_rectfill_template<T>(rasterBuffer, x, y, width, height, color); \ |
| } |
| } |
| |
| |
| QT_RECTFILL(quint32) |
| QT_RECTFILL(quint32) |
| QT_RECTFILL(quint16) |
| QT_RECTFILL(quint16) |
| QT_RECTFILL(qargb8565) |
| QT_RECTFILL(qargb8565) |
| QT_RECTFILL(qrgb666) |
| QT_RECTFILL(qrgb666) |
| QT_RECTFILL(qargb6666) |
| QT_RECTFILL(qargb6666) |
| QT_RECTFILL(qrgb555) |
| QT_RECTFILL(qrgb555) |
| QT_RECTFILL(qargb8555) |
| QT_RECTFILL(qargb8555) |
| QT_RECTFILL(qrgb888) |
| QT_RECTFILL(qrgb888) |
| QT_RECTFILL(qrgb444) |
| QT_RECTFILL(qrgb444) |
| QT_RECTFILL(qargb4444) |
| QT_RECTFILL(qargb4444) |
| #undef QT_RECTFILL |
| #undef QT_RECTFILL |
| |
| |
| inline static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, |
| inline static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, |
| int x, int y, int width, int height, |
| int x, int y, int width, int height, |
| quint32 color) |
| quint32 color) |
| { |
| { |
| qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), |
| qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), |
| INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); |
| INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); |
| } |
| } |
| |
| |
| |
| |
| // Map table for destination image format. Contains function pointers |
| // Map table for destination image format. Contains function pointers |
| // for blends of various types unto the destination |
| // for blends of various types unto the destination |
| |
| |
| DrawHelper qDrawHelper[QImage::NImageFormats] = |
| DrawHelper qDrawHelper[QImage::NImageFormats] = |
| { |
| { |
| // Format_Invalid, |
| // Format_Invalid, |
| { 0, 0, 0, 0, 0, 0 }, |
| { 0, 0, 0, 0, 0, 0 }, |
| // Format_Mono, |
| // Format_Mono, |
| { |
| { |
| blend_color_generic, |
| blend_color_generic, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_MonoLSB, |
| // Format_MonoLSB, |
| { |
| { |
| blend_color_generic, |
| blend_color_generic, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_Indexed8, |
| // Format_Indexed8, |
| { |
| { |
| blend_color_generic, |
| blend_color_generic, |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB32, |
| // Format_RGB32, |
| { |
| { |
| blend_color_argb, |
| blend_color_argb, |
| qt_gradient_quint32, |
| qt_gradient_quint32, |
| qt_bitmapblit_quint32, |
| qt_bitmapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_rectfill_quint32 |
| qt_rectfill_quint32 |
| }, |
| }, |
| // Format_ARGB32, |
| // Format_ARGB32, |
| { |
| { |
| blend_color_generic, |
| blend_color_generic, |
| qt_gradient_quint32, |
| qt_gradient_quint32, |
| qt_bitmapblit_quint32, |
| qt_bitmapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_rectfill_nonpremul_quint32 |
| qt_rectfill_nonpremul_quint32 |
| }, |
| }, |
| // Format_ARGB32_Premultiplied |
| // Format_ARGB32_Premultiplied |
| { |
| { |
| blend_color_argb, |
| blend_color_argb, |
| qt_gradient_quint32, |
| qt_gradient_quint32, |
| qt_bitmapblit_quint32, |
| qt_bitmapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphamapblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_alphargbblit_quint32, |
| qt_rectfill_quint32 |
| qt_rectfill_quint32 |
| }, |
| }, |
| // Format_RGB16 |
| // Format_RGB16 |
| { |
| { |
| blend_color_rgb16, |
| blend_color_rgb16, |
| qt_gradient_quint16, |
| qt_gradient_quint16, |
| qt_bitmapblit_quint16, |
| qt_bitmapblit_quint16, |
| qt_alphamapblit_quint16, |
| qt_alphamapblit_quint16, |
| 0, |
| 0, |
| qt_rectfill_quint16 |
| qt_rectfill_quint16 |
| }, |
| }, |
| // Format_ARGB8565_Premultiplied |
| // Format_ARGB8565_Premultiplied |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qargb8565), |
| SPANFUNC_POINTER_BLENDCOLOR(qargb8565), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qargb8565 |
| qt_rectfill_qargb8565 |
| }, |
| }, |
| // Format_RGB666 |
| // Format_RGB666 |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb666), |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb666), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qrgb666 |
| qt_rectfill_qrgb666 |
| }, |
| }, |
| // Format_ARGB6666_Premultiplied |
| // Format_ARGB6666_Premultiplied |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qargb6666), |
| SPANFUNC_POINTER_BLENDCOLOR(qargb6666), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qargb6666 |
| qt_rectfill_qargb6666 |
| }, |
| }, |
| // Format_RGB555 |
| // Format_RGB555 |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb555), |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb555), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qrgb555 |
| qt_rectfill_qrgb555 |
| }, |
| }, |
| // Format_ARGB8555_Premultiplied |
| // Format_ARGB8555_Premultiplied |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qargb8555), |
| SPANFUNC_POINTER_BLENDCOLOR(qargb8555), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qargb8555 |
| qt_rectfill_qargb8555 |
| }, |
| }, |
| // Format_RGB888 |
| // Format_RGB888 |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb888), |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb888), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qrgb888 |
| qt_rectfill_qrgb888 |
| }, |
| }, |
| // Format_RGB444 |
| // Format_RGB444 |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb444), |
| SPANFUNC_POINTER_BLENDCOLOR(qrgb444), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qrgb444 |
| qt_rectfill_qrgb444 |
| }, |
| }, |
| // Format_ARGB4444_Premultiplied |
| // Format_ARGB4444_Premultiplied |
| { |
| { |
| SPANFUNC_POINTER_BLENDCOLOR(qargb4444), |
| SPANFUNC_POINTER_BLENDCOLOR(qargb4444), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| SPANFUNC_POINTER(blend_src_generic, RegularSpans), |
| 0, 0, 0, |
| 0, 0, 0, |
| qt_rectfill_qargb4444 |
| qt_rectfill_qargb4444 |
| } |
| } |
| }; |
| }; |
| |
| |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| #if defined (Q_WS_QWS) && !defined(QT_NO_RASTERCALLBACKS) |
| DrawHelper qDrawHelperCallback[QImage::NImageFormats] = |
| DrawHelper qDrawHelperCallback[QImage::NImageFormats] = |
| { |
| { |
| // Format_Invalid, |
| // Format_Invalid, |
| { 0, 0, 0, 0, 0, 0 }, |
| { 0, 0, 0, 0, 0, 0 }, |
| // Format_Mono, |
| // Format_Mono, |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_MonoLSB, |
| // Format_MonoLSB, |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_Indexed8, |
| // Format_Indexed8, |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB32, |
| // Format_RGB32, |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB32, |
| // Format_ARGB32, |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB32_Premultiplied |
| // Format_ARGB32_Premultiplied |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB16 |
| // Format_RGB16 |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB8565_Premultiplied |
| // Format_ARGB8565_Premultiplied |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB666 |
| // Format_RGB666 |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB6666_Premultiplied |
| // Format_ARGB6666_Premultiplied |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB555 |
| // Format_RGB555 |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB8555_Premultiplied |
| // Format_ARGB8555_Premultiplied |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB888 |
| // Format_RGB888 |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_RGB444 |
| // Format_RGB444 |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| }, |
| }, |
| // Format_ARGB4444_Premultiplied |
| // Format_ARGB4444_Premultiplied |
| { |
| { |
| blend_color_generic_callback, |
| blend_color_generic_callback, |
| blend_src_generic<CallbackSpans>, |
| blend_src_generic<CallbackSpans>, |
| 0, 0, 0, 0 |
| 0, 0, 0, 0 |
| } |
| } |
| }; |
| }; |
| #endif |
| #endif |
| |
| |
| |
| |
| |
| |
| #if defined(Q_CC_MSVC) && !defined(_MIPS_) |
| #if defined(Q_CC_MSVC) && !defined(_MIPS_) |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void qt_memfill_template(DST *dest, SRC color, int count) |
| inline void qt_memfill_template(DST *dest, SRC color, int count) |
| { |
| { |
| const DST c = qt_colorConvert<DST, SRC>(color, 0); |
| const DST c = qt_colorConvert<DST, SRC>(color, 0); |
| while (count--) |
| while (count--) |
| *dest++ = c; |
| *dest++ = c; |
| } |
| } |
| |
| |
| #else |
| #else |
| |
| |
| template <class DST, class SRC> |
| template <class DST, class SRC> |
| inline void qt_memfill_template(DST *dest, SRC color, int count) |
| inline void qt_memfill_template(DST *dest, SRC color, int count) |
| { |
| { |
| const DST c = qt_colorConvert<DST, SRC>(color, 0); |
| const DST c = qt_colorConvert<DST, SRC>(color, 0); |
| int n = (count + 7) / 8; |
| int n = (count + 7) / 8; |
| switch (count & 0x07) |
| switch (count & 0x07) |
| { |
| { |
| case 0: do { *dest++ = c; |
| case 0: do { *dest++ = c; |
| case 7: *dest++ = c; |
| case 7: *dest++ = c; |
| case 6: *dest++ = c; |
| case 6: *dest++ = c; |
| case 5: *dest++ = c; |
| case 5: *dest++ = c; |
| case 4: *dest++ = c; |
| case 4: *dest++ = c; |
| case 3: *dest++ = c; |
| case 3: *dest++ = c; |
| case 2: *dest++ = c; |
| case 2: *dest++ = c; |
| case 1: *dest++ = c; |
| case 1: *dest++ = c; |
| } while (--n > 0); |
| } while (--n > 0); |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| inline void qt_memfill_template(quint16 *dest, quint16 value, int count) |
| inline void qt_memfill_template(quint16 *dest, quint16 value, int count) |
| { |
| { |
| if (count < 3) { |
| if (count < 3) { |
| switch (count) { |
| switch (count) { |
| case 2: *dest++ = value; |
| case 2: *dest++ = value; |
| case 1: *dest = value; |
| case 1: *dest = value; |
| } |
| } |
| return; |
| return; |
| } |
| } |
| |
| |
| const int align = (quintptr)(dest) & 0x3; |
| const int align = (quintptr)(dest) & 0x3; |
| switch (align) { |
| switch (align) { |
| case 2: *dest++ = value; --count; |
| case 2: *dest++ = value; --count; |
| } |
| } |
| |
| |
| const quint32 value32 = (value << 16) | value; |
| const quint32 value32 = (value << 16) | value; |
| qt_memfill(reinterpret_cast<quint32*>(dest), value32, count / 2); |
| qt_memfill(reinterpret_cast<quint32*>(dest), value32, count / 2); |
| if (count & 0x1) |
| if (count & 0x1) |
| dest[count - 1] = value; |
| dest[count - 1] = value; |
| } |
| } |
| #endif |
| #endif |
| |
| |
| static void qt_memfill_quint16(quint16 *dest, quint16 color, 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, quint16>(dest, color, count); |
| } |
| } |
| |
| |
| typedef void (*qt_memfill32_func)(quint32 *dest, quint32 value, int count); |
| typedef void (*qt_memfill32_func)(quint32 *dest, quint32 value, int count); |
| typedef void (*qt_memfill16_func)(quint16 *dest, quint16 value, int count); |
| typedef void (*qt_memfill16_func)(quint16 *dest, quint16 value, int count); |
| static void qt_memfill32_setup(quint32 *dest, quint32 value, int count); |
| static void qt_memfill32_setup(quint32 *dest, quint32 value, int count); |
| static void qt_memfill16_setup(quint16 *dest, quint16 value, int count); |
| static void qt_memfill16_setup(quint16 *dest, quint16 value, int count); |
| |
| |
| qt_memfill32_func qt_memfill32 = qt_memfill32_setup; |
| qt_memfill32_func qt_memfill32 = qt_memfill32_setup; |
| qt_memfill16_func qt_memfill16 = qt_memfill16_setup; |
| qt_memfill16_func qt_memfill16 = qt_memfill16_setup; |
| |
| |
| #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) |
| |
| // Move these to qdrawhelper_arm.c when all |
| |
| // functions are implemented using arm assembly. |
| |
| static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = { |
| |
| comp_func_solid_SourceOver, |
| |
| comp_func_solid_DestinationOver, |
| |
| comp_func_solid_Clear, |
| |
| comp_func_solid_Source, |
| |
| comp_func_solid_Destination, |
| |
| comp_func_solid_SourceIn, |
| |
| comp_func_solid_DestinationIn, |
| |
| comp_func_solid_SourceOut, |
| |
| comp_func_solid_DestinationOut, |
| |
| comp_func_solid_SourceAtop, |
| |
| comp_func_solid_DestinationAtop, |
| |
| comp_func_solid_XOR, |
| |
| comp_func_solid_Plus, |
| |
| comp_func_solid_Multiply, |
| |
| comp_func_solid_Screen, |
| |
| comp_func_solid_Overlay, |
| |
| comp_func_solid_Darken, |
| |
| comp_func_solid_Lighten, |
| |
| comp_func_solid_ColorDodge, |
| |
| comp_func_solid_ColorBurn, |
| |
| comp_func_solid_HardLight, |
| |
| comp_func_solid_SoftLight, |
| |
| comp_func_solid_Difference, |
| |
| comp_func_solid_Exclusion, |
| |
| rasterop_solid_SourceOrDestination, |
| |
| rasterop_solid_SourceAndDestination, |
| |
| rasterop_solid_SourceXorDestination, |
| |
| rasterop_solid_NotSourceAndNotDestination, |
| |
| rasterop_solid_NotSourceOrNotDestination, |
| |
| rasterop_solid_NotSourceXorDestination, |
| |
| rasterop_solid_NotSource, |
| |
| rasterop_solid_NotSourceAndDestination, |
| |
| rasterop_solid_SourceAndNotDestination |
| |
| }; |
| |
| |
| |
| static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = { |
| |
| comp_func_SourceOver_armv6, |
| |
| comp_func_DestinationOver, |
| |
| comp_func_Clear, |
| |
| comp_func_Source_armv6, |
| |
| comp_func_Destination, |
| |
| comp_func_SourceIn, |
| |
| comp_func_DestinationIn, |
| |
| comp_func_SourceOut, |
| |
| comp_func_DestinationOut, |
| |
| comp_func_SourceAtop, |
| |
| comp_func_DestinationAtop, |
| |
| comp_func_XOR, |
| |
| comp_func_Plus, |
| |
| comp_func_Multiply, |
| |
| comp_func_Screen, |
| |
| comp_func_Overlay, |
| |
| comp_func_Darken, |
| |
| comp_func_Lighten, |
| |
| comp_func_ColorDodge, |
| |
| comp_func_ColorBurn, |
| |
| comp_func_HardLight, |
| |
| comp_func_SoftLight, |
| |
| comp_func_Difference, |
| |
| comp_func_Exclusion, |
| |
| rasterop_SourceOrDestination, |
| |
| rasterop_SourceAndDestination, |
| |
| rasterop_SourceXorDestination, |
| |
| rasterop_NotSourceAndNotDestination, |
| |
| rasterop_NotSourceOrNotDestination, |
| |
| rasterop_NotSourceXorDestination, |
| |
| rasterop_NotSource, |
| |
| rasterop_NotSourceAndDestination, |
| |
| rasterop_SourceAndNotDestination |
| |
| }; |
| |
| |
| |
| static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData) |
| |
| { |
| |
| QSpanData *data = reinterpret_cast<QSpanData *>(userData); |
| |
| |
| |
| CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode]; |
| |
| while (count--) { |
| |
| uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; |
| |
| func(target, spans->len, data->solid.color, spans->coverage); |
| |
| ++spans; |
| |
| } |
| |
| } |
| |
| |
| |
| #endif // Q_CC_RVCT && QT_HAVE_ARMV6 |
| |
| |
| |
| |
| |
| void qInitDrawhelperAsm() |
| void qInitDrawhelperAsm() |
| { |
| { |
| |
| |
| qt_memfill32 = qt_memfill_template<quint32, quint32>; |
| qt_memfill32 = qt_memfill_template<quint32, quint32>; |
| qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>; |
| qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>; |
| |
| |
| CompositionFunction *functionForModeAsm = 0; |
| CompositionFunction *functionForModeAsm = 0; |
| CompositionFunctionSolid *functionForModeSolidAsm = 0; |
| CompositionFunctionSolid *functionForModeSolidAsm = 0; |
| |
| |
| const uint features = qDetectCPUFeatures(); |
| const uint features = qDetectCPUFeatures(); |
| if (false) { |
| if (false) { |
| #ifdef QT_HAVE_SSE2 |
| #ifdef QT_HAVE_SSE2 |
| } else if (features & SSE2) { |
| } else if (features & SSE2) { |
| qt_memfill32 = qt_memfill32_sse2; |
| qt_memfill32 = qt_memfill32_sse2; |
| qt_memfill16 = qt_memfill16_sse2; |
| qt_memfill16 = qt_memfill16_sse2; |
| qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_RGB32].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_ARGB32].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].bitmapBlit = qt_bitmapblit32_sse2; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse2; |
| #endif |
| #endif |
| #ifdef QT_HAVE_SSE |
| #ifdef QT_HAVE_SSE |
| } else if (features & SSE) { |
| } else if (features & SSE) { |
| // qt_memfill32 = qt_memfill32_sse; |
| // qt_memfill32 = qt_memfill32_sse; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse; |
| #ifdef QT_HAVE_3DNOW |
| #ifdef QT_HAVE_3DNOW |
| if (features & MMX3DNOW) { |
| if (features & MMX3DNOW) { |
| qt_memfill32 = qt_memfill32_sse3dnow; |
| qt_memfill32 = qt_memfill32_sse3dnow; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse3dnow; |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse3dnow; |
| } |
| } |
| #endif |
| #endif |
| #endif // SSE |
| #endif // SSE |
| #if defined(QT_HAVE_MMXEXT) && defined(QT_HAVE_SSE) |
| |
| } else if (features & MMXEXT) { |
| |
| qt_memfill32 = qt_memfill32_sse; |
| |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse; |
| |
| # ifdef QT_HAVE_3DNOW |
| |
| if (features & MMX3DNOW) { |
| |
| qt_memfill32 = qt_memfill32_sse3dnow; |
| |
| qDrawHelper[QImage::Format_RGB16].bitmapBlit = qt_bitmapblit16_sse3dnow; |
| |
| } |
| |
| # endif // 3DNOW |
| |
| #endif // MMXEXT |
| |
| } |
| } |
| #ifdef QT_HAVE_MMX |
| #ifdef QT_HAVE_MMX |
| if (features & MMX) { |
| if (features & MMX) { |
| functionForModeAsm = qt_functionForMode_MMX; |
| functionForModeAsm = qt_functionForMode_MMX; |
| |
| |
| functionForModeSolidAsm = qt_functionForModeSolid_MMX; |
| functionForModeSolidAsm = qt_functionForModeSolid_MMX; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_mmx; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_mmx; |
| #ifdef QT_HAVE_3DNOW |
| #ifdef QT_HAVE_3DNOW |
| if (features & MMX3DNOW) { |
| if (features & MMX3DNOW) { |
| functionForModeAsm = qt_functionForMode_MMX3DNOW; |
| functionForModeAsm = qt_functionForMode_MMX3DNOW; |
| functionForModeSolidAsm = qt_functionForModeSolid_MMX3DNOW; |
| functionForModeSolidAsm = qt_functionForModeSolid_MMX3DNOW; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_mmx3dnow; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_mmx3dnow; |
| } |
| } |
| #endif // 3DNOW |
| #endif // 3DNOW |
| |
| |
| extern void qt_blend_rgb32_on_rgb32_mmx(uchar *destPixels, int dbpl, |
| extern void qt_blend_rgb32_on_rgb32_mmx(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| extern void qt_blend_argb32_on_argb32_mmx(uchar *destPixels, int dbpl, |
| extern void qt_blend_argb32_on_argb32_mmx(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mmx; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mmx; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mmx; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_mmx; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mmx; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mmx; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mmx; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_mmx; |
| |
| |
| } |
| } |
| #endif // MMX |
| #endif // MMX |
| |
| |
| #ifdef QT_HAVE_SSE |
| #ifdef QT_HAVE_SSE |
| if (features & SSE) { |
| if (features & SSE) { |
| extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, |
| extern void qt_blend_rgb32_on_rgb32_sse(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, |
| extern void qt_blend_argb32_on_argb32_sse(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse; |
| } |
| } |
| #endif // SSE |
| #endif // SSE |
| |
| |
| #ifdef QT_HAVE_SSE2 |
| #ifdef QT_HAVE_SSE2 |
| if (features & SSE2) { |
| if (features & SSE2) { |
| extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, |
| extern void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, |
| extern void qt_blend_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_sse2; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_sse2; |
| } |
| } |
| |
| |
| #ifdef QT_HAVE_SSSE3 |
| #ifdef QT_HAVE_SSSE3 |
| if (features & SSSE3) { |
| if (features & SSSE3) { |
| extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, |
| extern void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, |
| const uchar *srcPixels, int sbpl, |
| const uchar *srcPixels, int sbpl, |
| int w, int h, |
| int w, int h, |
| int const_alpha); |
| int const_alpha); |
| |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; |
| } |
| } |
| #endif // SSSE3 |
| #endif // SSSE3 |
| |
| |
| #endif // SSE2 |
| #endif // SSE2 |
| |
| |
| #ifdef QT_HAVE_SSE |
| #ifdef QT_HAVE_SSE |
| if (features & SSE) { |
| if (features & SSE) { |
| functionForModeAsm = qt_functionForMode_SSE; |
| functionForModeAsm = qt_functionForMode_SSE; |
| functionForModeSolidAsm = qt_functionForModeSolid_SSE; |
| functionForModeSolidAsm = qt_functionForModeSolid_SSE; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse; |
| #ifdef QT_HAVE_3DNOW |
| #ifdef QT_HAVE_3DNOW |
| if (features & MMX3DNOW) { |
| if (features & MMX3DNOW) { |
| functionForModeAsm = qt_functionForMode_SSE3DNOW; |
| functionForModeAsm = qt_functionForMode_SSE3DNOW; |
| functionForModeSolidAsm = qt_functionForModeSolid_SSE3DNOW; |
| functionForModeSolidAsm = qt_functionForModeSolid_SSE3DNOW; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse3dnow; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_sse3dnow; |
| } |
| } |
| #endif // 3DNOW |
| #endif // 3DNOW |
| |
| |
| |
| |
| #ifdef QT_HAVE_SSE2 |
| #ifdef QT_HAVE_SSE2 |
| if (features & SSE2) { |
| if (features & SSE2) { |
| extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, |
| extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, |
| const uint *srcPixels, |
| const uint *srcPixels, |
| int length, |
| int length, |
| uint const_alpha); |
| uint const_alpha); |
| extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); |
| extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); |
| extern void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha); |
| extern void QT_FASTCALL comp_func_Plus_sse2(uint *dst, const uint *src, int length, uint const_alpha); |
| extern void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha); |
| extern void QT_FASTCALL comp_func_Source_sse2(uint *dst, const uint *src, int length, uint const_alpha); |
| |
| |
| functionForModeAsm[0] = comp_func_SourceOver_sse2; |
| functionForModeAsm[0] = comp_func_SourceOver_sse2; |
| functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_sse2; |
| functionForModeAsm[QPainter::CompositionMode_Source] = comp_func_Source_sse2; |
| functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; |
| functionForModeAsm[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; |
| functionForModeSolidAsm[0] = comp_func_solid_SourceOver_sse2; |
| functionForModeSolidAsm[0] = comp_func_solid_SourceOver_sse2; |
| } |
| } |
| #endif |
| #endif |
| } |
| } |
| #elif defined(QT_HAVE_SSE2) |
| #elif defined(QT_HAVE_SSE2) |
| // this is the special case when SSE2 is usable but MMX/SSE is not usable (e.g.: Windows x64 + visual studio) |
| // this is the special case when SSE2 is usable but MMX/SSE is not usable (e.g.: Windows x64 + visual studio) |
| if (features & SSE2) { |
| if (features & SSE2) { |
| functionForModeAsm = qt_functionForMode_onlySSE2; |
| functionForModeAsm = qt_functionForMode_onlySSE2; |
| functionForModeSolidAsm = qt_functionForModeSolid_onlySSE2; |
| functionForModeSolidAsm = qt_functionForModeSolid_onlySSE2; |
| } |
| } |
| #endif |
| #endif |
| |
| |
| #ifdef QT_HAVE_IWMMXT |
| #ifdef QT_HAVE_IWMMXT |
| if (features & IWMMXT) { |
| if (features & IWMMXT) { |
| functionForModeAsm = qt_functionForMode_IWMMXT; |
| functionForModeAsm = qt_functionForMode_IWMMXT; |
| functionForModeSolidAsm = qt_functionForModeSolid_IWMMXT; |
| functionForModeSolidAsm = qt_functionForModeSolid_IWMMXT; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_iwmmxt; |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_iwmmxt; |
| } |
| } |
| #endif // IWMMXT |
| #endif // IWMMXT |
| |
| |
| #if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6) |
| #if defined(QT_HAVE_ARM_SIMD) |
| functionForModeAsm = qt_functionForMode_ARMv6; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_arm_simd; |
| functionForModeSolidAsm = qt_functionForModeSolid_ARMv6; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_arm_simd; |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_arm_simd; |
| qt_memfill32 = qt_memfill32_armv6; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_arm_simd; |
| |
| |
| qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6; |
| |
| |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
| |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
| |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
| |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
| |
| #elif defined(QT_HAVE_NEON) |
| #elif defined(QT_HAVE_NEON) |
| if (features & NEON) { |
| if (features & NEON) { |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
| qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
| qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon; |
| qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon; |
| qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB16] = qt_blend_rgb16_on_argb32_neon; |
| qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon; |
| qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16_neon; |
| |
| |
| qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon; |
| qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16_neon; |
| qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon; |
| qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16_neon; |
| |
| |
| qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon; |
| qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16_neon; |
| qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon; |
| qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16_neon; |
| |
| |
| qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon; |
| qDrawHelper[QImage::Format_RGB16].alphamapBlit = qt_alphamapblit_quint16_neon; |
| |
| |
| functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; |
| functionForMode_C[QPainter::CompositionMode_SourceOver] = qt_blend_argb32_on_argb32_scanline_neon; |
| functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; |
| functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_neon; |
| functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon; |
| functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_neon; |
| destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; |
| destFetchProc[QImage::Format_RGB16] = qt_destFetchRGB16_neon; |
| destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; |
| destStoreProc[QImage::Format_RGB16] = qt_destStoreRGB16_neon; |
| |
| |
| qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon; |
| qMemRotateFunctions[QImage::Format_RGB16][0] = qt_memrotate90_16_neon; |
| qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon; |
| qMemRotateFunctions[QImage::Format_RGB16][2] = qt_memrotate270_16_neon; |
| qt_memfill32 = qt_memfill32_neon; |
| qt_memfill32 = qt_memfill32_neon; |
| } |
| } |
| #endif |
| #endif |
| |
| |
| if (functionForModeSolidAsm) { |
| if (functionForModeSolidAsm) { |
| const int destinationMode = QPainter::CompositionMode_Destination; |
| const int destinationMode = QPainter::CompositionMode_Destination; |
| functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; |
| functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; |
| |
| |
| // use the default qdrawhelper implementation for the |
| // use the default qdrawhelper implementation for the |
| // extended composition modes |
| // extended composition modes |
| for (int mode = 12; mode < 24; ++mode) |
| for (int mode = 12; mode < 24; ++mode) |
| functionForModeSolidAsm[mode] = functionForModeSolid_C[mode]; |
| functionForModeSolidAsm[mode] = functionForModeSolid_C[mode]; |
| |
| |
| functionForModeSolid = functionForModeSolidAsm; |
| functionForModeSolid = functionForModeSolidAsm; |
| } |
| } |
| if (functionForModeAsm) |
| if (functionForModeAsm) |
| functionForMode = functionForModeAsm; |
| functionForMode = functionForModeAsm; |
| |
| |
| qt_build_pow_tables(); |
| qt_build_pow_tables(); |
| } |
| } |
| |
| |
| static void qt_memfill32_setup(quint32 *dest, quint32 value, int count) |
| static void qt_memfill32_setup(quint32 *dest, quint32 value, int count) |
| { |
| { |
| qInitDrawhelperAsm(); |
| qInitDrawhelperAsm(); |
| qt_memfill32(dest, value, count); |
| qt_memfill32(dest, value, count); |
| } |
| } |
| |
| |
| static void qt_memfill16_setup(quint16 *dest, quint16 value, int count) |
| static void qt_memfill16_setup(quint16 *dest, quint16 value, int count) |
| { |
| { |
| qInitDrawhelperAsm(); |
| qInitDrawhelperAsm(); |
| qt_memfill16(dest, value, count); |
| qt_memfill16(dest, value, count); |
| } |
| } |
| |
| |
| #ifdef QT_QWS_DEPTH_GENERIC |
| #ifdef QT_QWS_DEPTH_GENERIC |
| |
| |
| int qrgb::bpp = 0; |
| int qrgb::bpp = 0; |
| int qrgb::len_red = 0; |
| int qrgb::len_red = 0; |
| int qrgb::len_green = 0; |
| int qrgb::len_green = 0; |
| int qrgb::len_blue = 0; |
| int qrgb::len_blue = 0; |
| int qrgb::len_alpha = 0; |
| int qrgb::len_alpha = 0; |
| int qrgb::off_red = 0; |
| int qrgb::off_red = 0; |
| int qrgb::off_green = 0; |
| int qrgb::off_green = 0; |
| int qrgb::off_blue = 0; |
| int qrgb::off_blue = 0; |
| int qrgb::off_alpha = 0; |
| int qrgb::off_alpha = 0; |
| |
| |
| template <typename SRC> |
| template <typename SRC> |
| Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_rgb(qrgb *dest, const SRC *src, |
| Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_rgb(qrgb *dest, const SRC *src, |
| int x, int y, int width, int height, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| int dstStride, int srcStride) |
| { |
| { |
| quint8 *dest8 = reinterpret_cast<quint8*>(dest) |
| quint8 *dest8 = reinterpret_cast<quint8*>(dest) |
| + y * dstStride + x * qrgb::bpp; |
| + y * dstStride + x * qrgb::bpp; |
| |
| |
| srcStride = srcStride / sizeof(SRC) - width; |
| srcStride = srcStride / sizeof(SRC) - width; |
| dstStride -= (width * qrgb::bpp); |
| dstStride -= (width * qrgb::bpp); |
| |
| |
| for (int j = 0; j < height; ++j) { |
| for (int j = 0; j < height; ++j) { |
| for (int i = 0; i < width; ++i) { |
| for (int i = 0; i < width; ++i) { |
| const quint32 v = qt_convertToRgb<SRC>(*src++); |
| const quint32 v = qt_convertToRgb<SRC>(*src++); |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| #if Q_BYTE_ORDER == Q_BIG_ENDIAN |
| for (int j = qrgb::bpp - 1; j >= 0; --j) |
| for (int j = qrgb::bpp - 1; j >= 0; --j) |
| *dest8++ = (v >> (8 * j)) & 0xff; |
| *dest8++ = (v >> (8 * j)) & 0xff; |
| #else |
| #else |
| for (int j = 0; j < qrgb::bpp; ++j) |
| for (int j = 0; j < qrgb::bpp; ++j) |
| *dest8++ = (v >> (8 * j)) & 0xff; |
| *dest8++ = (v >> (8 * j)) & 0xff; |
| #endif |
| #endif |
| } |
| } |
| |
| |
| dest8 += dstStride; |
| dest8 += dstStride; |
| src += srcStride; |
| src += srcStride; |
| } |
| } |
| } |
| } |
| |
| |
| template <> |
| template <> |
| void qt_rectconvert(qrgb *dest, const quint32 *src, |
| void qt_rectconvert(qrgb *dest, const quint32 *src, |
| int x, int y, int width, int height, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| int dstStride, int srcStride) |
| { |
| { |
| qt_rectconvert_rgb<quint32>(dest, src, x, y, width, height, |
| qt_rectconvert_rgb<quint32>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| dstStride, srcStride); |
| } |
| } |
| |
| |
| template <> |
| template <> |
| void qt_rectconvert(qrgb *dest, const quint16 *src, |
| void qt_rectconvert(qrgb *dest, const quint16 *src, |
| int x, int y, int width, int height, |
| int x, int y, int width, int height, |
| int dstStride, int srcStride) |
| int dstStride, int srcStride) |
| { |
| { |
| qt_rectconvert_rgb<quint16>(dest, src, x, y, width, height, |
| qt_rectconvert_rgb<quint16>(dest, src, x, y, width, height, |
| dstStride, srcStride); |
| dstStride, srcStride); |
| } |
| } |
| |
| |
| #endif // QT_QWS_DEPTH_GENERIC |
| #endif // QT_QWS_DEPTH_GENERIC |
| |
| |
| QT_END_NAMESPACE |
| QT_END_NAMESPACE |
| |
| |