fix off color interpolation

cpp was not clamping correctly color value interpolations. In certain scenarios, if lerping were negative, it would offset the color incorrectly.
the dart runtime doesn't need this fix, because the Color class does it internally.
This PR copies how dart clamps its colors.

Diffs=
d563202b4 fix off color interpolation (#6375)

Co-authored-by: hernan <hernan@rive.app>
diff --git a/.rive_head b/.rive_head
index 8b6016b..5e2637f 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-bd71143bc0964a789174f30f01d14fa551e33bb9
+d563202b4e186bc89fb6ef6ee55bceabac18e307
diff --git a/src/shapes/paint/color.cpp b/src/shapes/paint/color.cpp
index c5adba2..1c4cb1c 100644
--- a/src/shapes/paint/color.cpp
+++ b/src/shapes/paint/color.cpp
@@ -63,7 +63,7 @@
 
 static unsigned int lerp(unsigned int a, unsigned int b, float mix)
 {
-    return std::lround(a * (1.0f - mix) + b * mix);
+    return std::lround(std::max(0.0f, std::min(255.f, a * (1.0f - mix) + b * mix)));
 }
 
 ColorInt colorLerp(ColorInt from, ColorInt to, float mix)
diff --git a/test/color_test.cpp b/test/color_test.cpp
index 28792ec..3105ec8 100644
--- a/test/color_test.cpp
+++ b/test/color_test.cpp
@@ -26,3 +26,18 @@
     CHECK(color4fPremul[2] == Approx(color4f[2] * color4f[3]));
     CHECK(color4fPremul[3] == Approx(color4f[3]));
 }
+
+TEST_CASE("color lerp", "[color]")
+{
+    // Lerping this color with a mix value > 1 returns a negative value
+    // that overflows the unsigned int
+    // If this is not clamped correctly, the result would be off.
+    rive::ColorInt colorFrom = 0x90909090;
+    rive::ColorInt colorTo = 0x1E1E1E1E;
+    float mix = 1.3f;
+    rive::ColorInt colorLerped = rive::colorLerp(colorFrom, colorTo, mix);
+    CHECK(rive::colorRed(colorLerped) == 0);
+    CHECK(rive::colorGreen(colorLerped) == 0);
+    CHECK(rive::colorBlue(colorLerped) == 0);
+    CHECK(rive::colorAlpha(colorLerped) == 0);
+}