Avoid overflows in gradient calculations
Avoid the optimized fixed-point function for vertical gradients if the parameters are out of range for that. Fall back to the general gradient function in that case. Fixes: QTBUG-120331 Pick-to: 6.5 6.2 Change-Id: Idf116f0077403531d9ea414e3043fdc92b6fe4a9 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> (cherry picked from commit ade33a91442f8085a7ddeb8e6fdf33463103b119) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
d77e099200
commit
f02ccd86c7
@ -4973,16 +4973,11 @@ void qBlendTexture(int count, const QT_FT_Span *spans, void *userData)
|
|||||||
proc(count, spans, 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
|
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:
|
||||||
@ -4997,8 +4992,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.
|
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);
|
qreal ryinc = 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 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--) {
|
while (count--) {
|
||||||
int y = spans->y;
|
int y = spans->y;
|
||||||
@ -5011,21 +5030,20 @@ static void blend_vertical_gradient_argb(int count, const QT_FT_Span *spans, voi
|
|||||||
funcSolid(dst, spans->len, color, spans->coverage);
|
funcSolid(dst, spans->len, color, spans->coverage);
|
||||||
++spans;
|
++spans;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<ProcessSpans blend_color>
|
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);
|
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
|
||||||
|
|
||||||
LinearGradientValues linear;
|
LinearGradientValues linear;
|
||||||
getLinearGradientValues(&linear, data);
|
getLinearGradientValues(&linear, data);
|
||||||
|
|
||||||
// Based on the same logic as blend_vertical_gradient_argb.
|
int yinc(0), off(0);
|
||||||
|
if (!calculate_fixed_gradient_factors(count, spans, data, linear, &yinc, &off))
|
||||||
const int gss = GRADIENT_STOPTABLE_SIZE - 1;
|
return false;
|
||||||
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));
|
|
||||||
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
int y = spans->y;
|
int y = spans->y;
|
||||||
@ -5038,6 +5056,7 @@ static void blend_vertical_gradient(int count, const QT_FT_Span *spans, void *us
|
|||||||
blend_color(1, spans, userData);
|
blend_color(1, spans, userData);
|
||||||
++spans;
|
++spans;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
|
void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
|
||||||
@ -5052,8 +5071,8 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
|
|||||||
break;
|
break;
|
||||||
case QImage::Format_RGB32:
|
case QImage::Format_RGB32:
|
||||||
case QImage::Format_ARGB32_Premultiplied:
|
case QImage::Format_ARGB32_Premultiplied:
|
||||||
if (isVerticalGradient)
|
if (isVerticalGradient && blend_vertical_gradient_argb(count, spans, userData))
|
||||||
return blend_vertical_gradient_argb(count, spans, userData);
|
return;
|
||||||
return blend_src_generic(count, spans, userData);
|
return blend_src_generic(count, spans, userData);
|
||||||
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
|
#if defined(__SSE2__) || defined(__ARM_NEON__) || (Q_PROCESSOR_WORDSIZE == 8)
|
||||||
case QImage::Format_ARGB32:
|
case QImage::Format_ARGB32:
|
||||||
@ -5075,8 +5094,8 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
|
|||||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||||
#endif
|
#endif
|
||||||
#if QT_CONFIG(raster_64bit)
|
#if QT_CONFIG(raster_64bit)
|
||||||
if (isVerticalGradient)
|
if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData))
|
||||||
return blend_vertical_gradient<blend_color_generic_rgb64>(count, spans, userData);
|
return;
|
||||||
return blend_src_generic_rgb64(count, spans, userData);
|
return blend_src_generic_rgb64(count, spans, userData);
|
||||||
#endif // QT_CONFIG(raster_64bit)
|
#endif // QT_CONFIG(raster_64bit)
|
||||||
#if QT_CONFIG(raster_fp)
|
#if QT_CONFIG(raster_fp)
|
||||||
@ -5086,13 +5105,13 @@ void qBlendGradient(int count, const QT_FT_Span *spans, void *userData)
|
|||||||
case QImage::Format_RGBX32FPx4:
|
case QImage::Format_RGBX32FPx4:
|
||||||
case QImage::Format_RGBA32FPx4:
|
case QImage::Format_RGBA32FPx4:
|
||||||
case QImage::Format_RGBA32FPx4_Premultiplied:
|
case QImage::Format_RGBA32FPx4_Premultiplied:
|
||||||
if (isVerticalGradient)
|
if (isVerticalGradient && blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData))
|
||||||
return blend_vertical_gradient<blend_color_generic_fp>(count, spans, userData);
|
return;
|
||||||
return blend_src_generic_fp(count, spans, userData);
|
return blend_src_generic_fp(count, spans, userData);
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
if (isVerticalGradient)
|
if (isVerticalGradient && blend_vertical_gradient<blend_color_generic>(count, spans, userData))
|
||||||
return blend_vertical_gradient<blend_color_generic>(count, spans, userData);
|
return;
|
||||||
return blend_src_generic(count, spans, userData);
|
return blend_src_generic(count, spans, userData);
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user