diff --git a/servo/components/style/properties/helpers/animated_properties.mako.rs b/servo/components/style/properties/helpers/animated_properties.mako.rs index 1e813ba78e18..642f25c7ef3a 100644 --- a/servo/components/style/properties/helpers/animated_properties.mako.rs +++ b/servo/components/style/properties/helpers/animated_properties.mako.rs @@ -390,12 +390,23 @@ impl Interpolate for BackgroundSize { impl Interpolate for RGBA { #[inline] fn interpolate(&self, other: &RGBA, progress: f64) -> Result { - Ok(RGBA { - red: try!(self.red.interpolate(&other.red, progress)), - green: try!(self.green.interpolate(&other.green, progress)), - blue: try!(self.blue.interpolate(&other.blue, progress)), - alpha: try!(self.alpha.interpolate(&other.alpha, progress)), - }) + fn clamp(val: f32) -> f32 { + val.max(0.).min(1.) + } + + let alpha = clamp(try!(self.alpha.interpolate(&other.alpha, progress))); + if alpha == 0. { + Ok(RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) + } else { + Ok(RGBA { red: clamp(try!((self.red * self.alpha).interpolate(&(other.red * other.alpha), progress)) + * 1. / alpha), + green: clamp(try!((self.green * self.alpha).interpolate(&(other.green * other.alpha), progress)) + * 1. / alpha), + blue: clamp(try!((self.blue * self.alpha).interpolate(&(other.blue * other.alpha), progress)) + * 1. / alpha), + alpha: alpha + }) + } } } diff --git a/servo/tests/unit/style/animated_properties.rs b/servo/tests/unit/style/animated_properties.rs new file mode 100644 index 000000000000..af9d14617873 --- /dev/null +++ b/servo/tests/unit/style/animated_properties.rs @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use cssparser::{Color, RGBA}; +use style::properties::animated_properties::Interpolate; + +#[test] +fn test_rgba_color_interepolation() { + assert_eq!(Color::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 }), 1.0).unwrap(), + Color::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 })); + + assert_eq!(Color::RGBA(RGBA { red: 1.0, green: 0.0, blue: 0.0, alpha: 0.6 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 1.0, blue: 0.0, alpha: 0.4 }), 0.5).unwrap(), + Color::RGBA(RGBA { red: 0.6, green: 0.4, blue: 0.0, alpha: 0.5 })); + + // Some cubic-bezier functions produce values that are out of range [0, 1]. + // Unclamped cases. + assert_eq!(Color::RGBA(RGBA { red: 0.3, green: 0.0, blue: 0.0, alpha: 0.4 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 1.0, blue: 0.0, alpha: 0.6 }), -0.5).unwrap(), + Color::RGBA(RGBA { red: 0.6, green: 0.0, blue: 0.0, alpha: 0.3 })); + + assert_eq!(Color::RGBA(RGBA { red: 1.0, green: 0.0, blue: 0.0, alpha: 0.6 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 0.3, blue: 0.0, alpha: 0.4 }), 1.5).unwrap(), + Color::RGBA(RGBA { red: 0.0, green: 0.6, blue: 0.0, alpha: 0.3 })); + + // Clamped cases. + assert_eq!(Color::RGBA(RGBA { red: 1.0, green: 0.0, blue: 0.0, alpha: 0.8 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 1.0, blue: 0.0, alpha: 0.2 }), -0.5).unwrap(), + Color::RGBA(RGBA { red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0 })); + + assert_eq!(Color::RGBA(RGBA { red: 1.0, green: 0.0, blue: 0.0, alpha: 0.8 }).interpolate( + &Color::RGBA(RGBA { red: 0.0, green: 1.0, blue: 0.0, alpha: 0.2 }), 1.5).unwrap(), + Color::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0 })); +} diff --git a/servo/tests/unit/style/lib.rs b/servo/tests/unit/style/lib.rs index f2be3da2307f..c9a04d885291 100644 --- a/servo/tests/unit/style/lib.rs +++ b/servo/tests/unit/style/lib.rs @@ -22,6 +22,7 @@ extern crate style; extern crate style_traits; extern crate test; +mod animated_properties; mod atomic_refcell; mod attr; mod cache;