From a5a8aae368e010dcdcac0d395b3272fddbda5d45 Mon Sep 17 00:00:00 2001 From: Gleb Mazovetskiy Date: Wed, 30 Mar 2022 10:37:48 +0100 Subject: [PATCH] Fix underflow in `BilinearScale32` Fixes funky hardware cursor colors during fade transitions. Refs #4206 --- Source/utils/sdl_bilinear_scale.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Source/utils/sdl_bilinear_scale.cpp b/Source/utils/sdl_bilinear_scale.cpp index e940e305a..8f36fa2bc 100644 --- a/Source/utils/sdl_bilinear_scale.cpp +++ b/Source/utils/sdl_bilinear_scale.cpp @@ -48,7 +48,18 @@ uint8_t MixColorsWithAlpha(uint8_t first, uint8_t firstAlpha, const int firstWithAlpha = first * firstAlpha; const int secondWithAlpha = second * secondAlpha; - return ToInt((secondWithAlpha - firstWithAlpha) * (ratio / mixedAlpha)) + firstWithAlpha / mixedAlpha; + // We want to calculate: + // + // (ToInt((secondWithAlpha - firstWithAlpha) * ratio) + firstWithAlpha) / mixedAlpha + // + // However, the above written as-is can overflow in the argument to `ToInt`. + // To avoid the overflow we divide each term by `mixedAlpha` separately. + // + // This would be lower precision and could result in a negative overall result, + // so we do the rounding integer division for each term (instead of a truncating one): + // + // (a + (a - 1)) / b` + return ToInt((secondWithAlpha - firstWithAlpha) * ((ratio + (mixedAlpha - 1)) / mixedAlpha)) + (firstWithAlpha + (mixedAlpha - 1)) / mixedAlpha; } } // namespace