src/gui/painting/qdrawhelper.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    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,
  7717     MMX3DNOW    = 0x4,
  7724     MMX3DNOW    = 0x4,
  7718     MMX3DNOWEXT = 0x8,
  7725     MMX3DNOWEXT = 0x8,
  7719     SSE         = 0x10,
  7726     SSE         = 0x10,
  7720     SSE2        = 0x20,
  7727     SSE2        = 0x20,
  7721     CMOV        = 0x40,
  7728     CMOV        = 0x40,
  7722     IWMMXT      = 0x80
  7729     IWMMXT      = 0x80,
       
  7730     NEON        = 0x100
  7723 };
  7731 };
  7724 
  7732 
  7725 static uint detectCPUFeatures()
  7733 static uint detectCPUFeatures()
  7726 {
  7734 {
  7727 #if defined (Q_OS_WINCE)
  7735 #if defined (Q_OS_WINCE)
  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