42 #include <private/qdrawhelper_p.h> |
42 #include <private/qdrawhelper_p.h> |
43 #include <private/qpaintengine_raster_p.h> |
43 #include <private/qpaintengine_raster_p.h> |
44 #include <private/qpainter_p.h> |
44 #include <private/qpainter_p.h> |
45 #include <private/qdrawhelper_x86_p.h> |
45 #include <private/qdrawhelper_x86_p.h> |
46 #include <private/qdrawhelper_armv6_p.h> |
46 #include <private/qdrawhelper_armv6_p.h> |
|
47 #include <private/qdrawhelper_neon_p.h> |
47 #include <private/qmath_p.h> |
48 #include <private/qmath_p.h> |
48 #include <qmath.h> |
49 #include <qmath.h> |
49 |
50 |
50 QT_BEGIN_NAMESPACE |
51 QT_BEGIN_NAMESPACE |
51 |
52 |
1180 const uint *end = buffer + length; |
1181 const uint *end = buffer + length; |
1181 if (affine) { |
1182 if (affine) { |
1182 rx -= data->gradient.conical.center.x; |
1183 rx -= data->gradient.conical.center.x; |
1183 ry -= data->gradient.conical.center.y; |
1184 ry -= data->gradient.conical.center.y; |
1184 while (buffer < end) { |
1185 while (buffer < end) { |
1185 qreal angle = atan2(ry, rx) + data->gradient.conical.angle; |
1186 qreal angle = qAtan2(ry, rx) + data->gradient.conical.angle; |
1186 |
1187 |
1187 *buffer = qt_gradient_pixel(&data->gradient, 1 - angle / (2*Q_PI)); |
1188 *buffer = qt_gradient_pixel(&data->gradient, 1 - angle / (2*Q_PI)); |
1188 |
1189 |
1189 rx += data->m11; |
1190 rx += data->m11; |
1190 ry += data->m12; |
1191 ry += data->m12; |
1194 qreal rw = data->m23 * (y + 0.5) |
1195 qreal rw = data->m23 * (y + 0.5) |
1195 + data->m33 + data->m13 * (x + 0.5); |
1196 + data->m33 + data->m13 * (x + 0.5); |
1196 if (!rw) |
1197 if (!rw) |
1197 rw = 1; |
1198 rw = 1; |
1198 while (buffer < end) { |
1199 while (buffer < end) { |
1199 qreal angle = atan2(ry/rw - data->gradient.conical.center.x, |
1200 qreal angle = qAtan2(ry/rw - data->gradient.conical.center.x, |
1200 rx/rw - data->gradient.conical.center.y) |
1201 rx/rw - data->gradient.conical.center.y) |
1201 + data->gradient.conical.angle; |
1202 + data->gradient.conical.angle; |
1202 |
1203 |
1203 *buffer = qt_gradient_pixel(&data->gradient, 1. - angle / (2*Q_PI)); |
1204 *buffer = qt_gradient_pixel(&data->gradient, 1. - angle / (2*Q_PI)); |
1204 |
1205 |
2384 else |
2385 else |
2385 comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
2386 comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha)); |
2386 } |
2387 } |
2387 |
2388 |
2388 /* |
2389 /* |
2389 if 2.Sca < Sa |
2390 if 2.Sca <= Sa |
2390 Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) |
2391 Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) |
2391 otherwise if 8.Dca <= Da |
2392 otherwise if 2.Sca > Sa and 4.Dca <= Da |
2392 Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) |
2393 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) |
2393 otherwise |
2394 otherwise if 2.Sca > Sa and 4.Dca > Da |
2394 Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) |
2395 Dca' = Dca.Sa + Da.(2.Sca - Sa).((Dca/Da)^0.5 - Dca/Da) + Sca.(1 - Da) + Dca.(1 - Sa) |
2395 */ |
2396 */ |
2396 static inline int soft_light_op(int dst, int src, int da, int sa) |
2397 static inline int soft_light_op(int dst, int src, int da, int sa) |
2397 { |
2398 { |
2398 const int src2 = src << 1; |
2399 const int src2 = src << 1; |
2399 const int dst_np = da != 0 ? (255 * dst) / da : 0; |
2400 const int dst_np = da != 0 ? (255 * dst) / da : 0; |
2400 const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; |
2401 const int temp = (src * (255 - da) + dst * (255 - sa)) * 255; |
2401 |
2402 |
2402 if (src2 < sa) |
2403 if (src2 < sa) |
2403 return (dst * ((sa * 255) - (255 - dst_np) * (src2 - sa)) + temp) / 65025; |
2404 return (dst * (sa * 255 + (src2 - sa) * (255 - dst_np)) + temp) / 65025; |
2404 else if (8 * dst <= da) |
2405 else if (4 * dst <= da) |
2405 return (dst * ((sa * 255) - ((255 - dst_np) * (src2 - sa) * ((3 * 255) - 8 * dst_np)) / 255) + temp) / 65025; |
2406 return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025; |
2406 else { |
2407 else { |
2407 // sqrt is too expensive to do three times per pixel, so skipping it for now |
2408 return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025; |
2408 // a future possibility is to use a LUT |
|
2409 return ((dst * sa * 255) + (int(dst_np) * da - (dst * 255)) * (src2 - sa) + temp) / 65025; |
|
2410 } |
2409 } |
2411 } |
2410 } |
2412 |
2411 |
2413 template <typename T> |
2412 template <typename T> |
2414 Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) |
2413 Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage) |
7140 qt_pow_rgb_gamma[i] = uchar(i); |
7139 qt_pow_rgb_gamma[i] = uchar(i); |
7141 qt_pow_rgb_invgamma[i] = uchar(i); |
7140 qt_pow_rgb_invgamma[i] = uchar(i); |
7142 } |
7141 } |
7143 #else |
7142 #else |
7144 for (int i=0; i<256; ++i) { |
7143 for (int i=0; i<256; ++i) { |
7145 qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255.0), smoothing) * 255)); |
7144 qt_pow_rgb_gamma[i] = uchar(qRound(qPow(i / qreal(255.0), smoothing) * 255)); |
7146 qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255.), 1 / smoothing) * 255)); |
7145 qt_pow_rgb_invgamma[i] = uchar(qRound(qPow(i / qreal(255.), 1 / smoothing) * 255)); |
7147 } |
7146 } |
7148 #endif |
7147 #endif |
7149 |
7148 |
7150 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
7149 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
7151 const qreal gray_gamma = 2.31; |
7150 const qreal gray_gamma = 2.31; |
7152 for (int i=0; i<256; ++i) |
7151 for (int i=0; i<256; ++i) |
7153 qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047)); |
7152 qt_pow_gamma[i] = uint(qRound(qPow(i / qreal(255.), gray_gamma) * 2047)); |
7154 for (int i=0; i<2048; ++i) |
7153 for (int i=0; i<2048; ++i) |
7155 qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255)); |
7154 qt_pow_invgamma[i] = uchar(qRound(qPow(i / 2047.0, 1 / gray_gamma) * 255)); |
7156 #endif |
7155 #endif |
7157 } |
7156 } |
7158 |
7157 |
7159 static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
7158 static inline void rgbBlendPixel(quint32 *dst, int coverage, int sr, int sg, int sb) |
7160 { |
7159 { |
7421 QT_RECTFILL(qargb8555) |
7420 QT_RECTFILL(qargb8555) |
7422 QT_RECTFILL(qrgb888) |
7421 QT_RECTFILL(qrgb888) |
7423 QT_RECTFILL(qrgb444) |
7422 QT_RECTFILL(qrgb444) |
7424 QT_RECTFILL(qargb4444) |
7423 QT_RECTFILL(qargb4444) |
7425 #undef QT_RECTFILL |
7424 #undef QT_RECTFILL |
|
7425 |
|
7426 inline static void qt_rectfill_nonpremul_quint32(QRasterBuffer *rasterBuffer, |
|
7427 int x, int y, int width, int height, |
|
7428 quint32 color) |
|
7429 { |
|
7430 qt_rectfill<quint32>(reinterpret_cast<quint32 *>(rasterBuffer->buffer()), |
|
7431 INV_PREMUL(color), x, y, width, height, rasterBuffer->bytesPerLine()); |
|
7432 } |
7426 |
7433 |
7427 |
7434 |
7428 // Map table for destination image format. Contains function pointers |
7435 // Map table for destination image format. Contains function pointers |
7429 // for blends of various types unto the destination |
7436 // for blends of various types unto the destination |
7430 |
7437 |
7464 blend_color_generic, |
7471 blend_color_generic, |
7465 qt_gradient_quint32, |
7472 qt_gradient_quint32, |
7466 qt_bitmapblit_quint32, |
7473 qt_bitmapblit_quint32, |
7467 qt_alphamapblit_quint32, |
7474 qt_alphamapblit_quint32, |
7468 qt_alphargbblit_quint32, |
7475 qt_alphargbblit_quint32, |
7469 qt_rectfill_quint32 |
7476 qt_rectfill_nonpremul_quint32 |
7470 }, |
7477 }, |
7471 // Format_ARGB32_Premultiplied |
7478 // Format_ARGB32_Premultiplied |
7472 { |
7479 { |
7473 blend_color_argb, |
7480 blend_color_argb, |
7474 qt_gradient_quint32, |
7481 qt_gradient_quint32, |
7743 return 0; |
7751 return 0; |
7744 #elif defined(QT_HAVE_IWMMXT) |
7752 #elif defined(QT_HAVE_IWMMXT) |
7745 // runtime detection only available when running as a previlegied process |
7753 // runtime detection only available when running as a previlegied process |
7746 static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt(); |
7754 static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt(); |
7747 return doIWMMXT ? IWMMXT : 0; |
7755 return doIWMMXT ? IWMMXT : 0; |
|
7756 #elif defined(QT_HAVE_NEON) |
|
7757 static const bool doNEON = !qgetenv("QT_NO_NEON").toInt(); |
|
7758 return doNEON ? NEON : 0; |
7748 #else |
7759 #else |
7749 uint features = 0; |
7760 uint features = 0; |
7750 #if defined(__x86_64__) || defined(Q_OS_WIN64) |
7761 #if defined(__x86_64__) || defined(Q_OS_WIN64) |
7751 features = MMX|SSE|SSE2|CMOV; |
7762 features = MMX|SSE|SSE2|CMOV; |
7752 #elif defined(__ia64__) |
7763 #elif defined(__ia64__) |
8114 |
8125 |
8115 qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
8126 qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
8116 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
8127 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6; |
8117 qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
8128 qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
8118 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
8129 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6; |
8119 #endif // Q_CC_RVCT && QT_HAVE_ARMV6 |
8130 #elif defined(QT_HAVE_NEON) |
|
8131 if (features & NEON) { |
|
8132 qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
|
8133 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; |
|
8134 qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
|
8135 qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; |
|
8136 } |
|
8137 #endif |
8120 |
8138 |
8121 if (functionForModeSolidAsm) { |
8139 if (functionForModeSolidAsm) { |
8122 const int destinationMode = QPainter::CompositionMode_Destination; |
8140 const int destinationMode = QPainter::CompositionMode_Destination; |
8123 functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; |
8141 functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode]; |
8124 |
8142 |