diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/painting/qdrawhelper.cpp | 69 |
1 files changed, 44 insertions, 25 deletions
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 8b17a4fedc..b7a943be38 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5010,16 +5010,11 @@ void qBlendTexture(int count, const QT_FT_Span *spans, void *userData) proc(count, spans, userData); } -static void blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, void *userData) +static inline bool calculate_fixed_gradient_factors(int count, const QT_FT_Span *spans, + const QSpanData *data, + const LinearGradientValues &linear, + int *pyinc, int *poff) { - QSpanData *data = reinterpret_cast<QSpanData *>(userData); - - LinearGradientValues linear; - getLinearGradientValues(&linear, data); - - CompositionFunctionSolid funcSolid = - functionForModeSolid[data->rasterBuffer->compositionMode]; - /* The logic for vertical gradient calculations is a mathematically reduced copy of that in fetchLinearGradient() - which is basically: @@ -5034,8 +5029,32 @@ static void blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, voi This has then been converted to fixed point to improve performance. */ const int gss = GRADIENT_STOPTABLE_SIZE - 1; - int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); - int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); + qreal ryinc = linear.dy * data->m22 * gss * FIXPT_SIZE; + qreal roff = (linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss * FIXPT_SIZE; + const int limit = std::numeric_limits<int>::max() - FIXPT_SIZE; + if (count && (std::fabs(ryinc) < limit) && (std::fabs(roff) < limit) + && (std::fabs(ryinc * spans->y + roff) < limit) + && (std::fabs(ryinc * (spans + count - 1)->y + roff) < limit)) { + *pyinc = int(ryinc); + *poff = int(roff); + return true; + } + return false; +} + +static bool blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, void *userData) +{ + QSpanData *data = reinterpret_cast<QSpanData *>(userData); + + LinearGradientValues linear; + getLinearGradientValues(&linear, data); + + CompositionFunctionSolid funcSolid = + functionForModeSolid[data->rasterBuffer->compositionMode]; + + int yinc(0), off(0); + if (!calculate_fixed_gradient_factors(count, spans, data, linear, &yinc, &off)) + return false; while (count--) { int y = spans->y; @@ -5048,21 +5067,20 @@ static void blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, voi funcSolid(dst, spans->len, color, spans->coverage); ++spans; } + return true; } template<ProcessSpans blend_color> -static void blend_vertical_gradient(int count, const QT_FT_Span *spans, void *userData) +static bool blend_vertical_gradient(int count, const QT_FT_Span *spans, void *userData) { QSpanData *data = reinterpret_cast<QSpanData *>(userData); LinearGradientValues linear; getLinearGradientValues(&linear, data); - // Based on the same logic as blend_vertical_gradient_argb. - - const int gss = GRADIENT_STOPTABLE_SIZE - 1; - int yinc = int((linear.dy * data->m22 * gss) * FIXPT_SIZE); - int off = int((((linear.dy * (data->m22 * qreal(0.5) + data->dy) + linear.off) * gss) * FIXPT_SIZE)); + int yinc(0), off(0); + if (!calculate_fixed_gradient_factors(count, spans, data, linear, &yinc, &off)) + return false; while (count--) { int y = spans->y; @@ -5075,6 +5093,7 @@ static void blend_vertical_gradient(int count, const QT_FT_Span *spans, void *us blend_color(1, spans, userData); ++spans; } + return true; } void qBlendGradient(int count, const QT_FT_Span *spans, void *userData) @@ -5089,8 +5108,8 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData) break; case QImage::Format_RGB32: case QImage::Format_ARGB32_Premultiplied: - if (isVerticalGradient) - return blend_vertical_gradient_argb(count, spans, userData); + if (isVerticalGradient && blend_vertical_gradient_argb(count, spans, userData)) + return; return blend_src_generic(count, spans, userData); #if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8) case QImage::Format_ARGB32: @@ -5112,8 +5131,8 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData) case QImage::Format_RGBA32FPx4_Premultiplied: #endif #if QT_CONFIG(raster_64bit) - if (isVerticalGradient) - return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData); + if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData)) + return; return blend_src_generic_rgb64(count, spans, userData); #endif // QT_CONFIG(raster_64bit) #if QT_CONFIG(raster_fp) @@ -5123,13 +5142,13 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData) case QImage::Format_RGBX32FPx4: case QImage::Format_RGBA32FPx4: case QImage::Format_RGBA32FPx4_Premultiplied: - if (isVerticalGradient) - return blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData); + if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData)) + return; return blend_src_generic_fp(count, spans, userData); #endif default: - if (isVerticalGradient) - return blend_vertical_gradient<blend_color_generic>(count, spans, userData); + if (isVerticalGradient && blend_vertical_gradient<blend_color_generic>(count, spans, userData)) + return; return blend_src_generic(count, spans, userData); } Q_UNREACHABLE(); |