From 1f0438e7fe7a6580116d95a922948ee63c7547b4 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Tue, 11 Feb 2020 10:00:34 +0100 Subject: [PATCH] gsk: Fix angle normalization I was getting assertions that normalize_angle() failed the result < 260 check. Doing some research on this it turns out to be a precision issue. If the incomming angle is very slightly below zero, then adding 360 to it may end up with exactly 360. I simplified the code a bit to avoid division and rounding, because in practice most angles will be "just outside" the 0-360 degree anyway. And i also added a workaround for the "result is 360" case by just setting it to 0. --- gsk/gsktransform.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c index b474ec4114..c8e0d321b7 100644 --- a/gsk/gsktransform.c +++ b/gsk/gsktransform.c @@ -821,20 +821,28 @@ static const GskTransformClass GSK_ROTATE_TRANSFORM_CLASS = static inline float normalize_angle (float angle) { - float f; if (angle >= 0 && angle < 360) return angle; - f = angle - (360 * ((int)(angle / 360.0))); + while (angle >= 360) + angle -= 360; + while (angle < 0) + angle += 360; - if (f < 0) - f = 360 + f; + /* Due to precision issues we may end up with a result that is just + * past the allowed range when rounded. For example, something like + * -epsilon + 360 when rounded to a float may end up with 360. + * So, we handle these cases by returning the exact value 0. + */ - g_assert (f < 360.0); - g_assert (f >= 0.0); + if (angle >= 360) + angle = 0; - return f; + g_assert (angle < 360.0); + g_assert (angle >= 0.0); + + return angle; } /**