servo: Merge #17157 - Remove some redundant animation interpolation code (from upsuper:animation-type); r=<try>
authorXidorn Quan <me@upsuper.org>
Sun, 04 Jun 2017 19:34:05 -0700
changeset 412711 b16a3c81c33981da108dbe259dfcc93d3b705113
parent 412710 7513f724a303b272b1b29990dd9b39495b9dbccb
child 412712 7d5df2dead2c9edaa41688a82d9d9dcc86529ef2
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #17157 - Remove some redundant animation interpolation code (from upsuper:animation-type); r=<try> Source-Repo: https://github.com/servo/servo Source-Revision: 67eaae82ed59fffbcda3c4c98c949537a232f5c9
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/tests/unit/style/animated_properties.rs
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -289,19 +289,24 @@ impl<'a> From<TransitionProperty> for Pr
 
 /// An animated property interpolation between two computed values for that
 /// property.
 #[derive(Clone, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum AnimatedProperty {
     % for prop in data.longhands:
         % if prop.animatable:
+            <%
+                if prop.is_animatable_with_computed_value:
+                    value_type = "longhands::{}::computed_value::T".format(prop.ident)
+                else:
+                    value_type = prop.animation_value_type
+            %>
             /// ${prop.name}
-            ${prop.camel_case}(longhands::${prop.ident}::computed_value::T,
-                               longhands::${prop.ident}::computed_value::T),
+            ${prop.camel_case}(${value_type}, ${value_type}),
         % endif
     % endfor
 }
 
 impl AnimatedProperty {
     /// Get the name of this property.
     pub fn name(&self) -> &'static str {
         match *self {
@@ -351,16 +356,19 @@ impl AnimatedProperty {
                         % if prop.animation_value_type == "discrete":
                             let value = if progress < 0.5 { from.clone() } else { to.clone() };
                         % else:
                             let value = match from.interpolate(to, progress) {
                                 Ok(value) => value,
                                 Err(()) => return,
                             };
                         % endif
+                        % if not prop.is_animatable_with_computed_value:
+                            let value: longhands::${prop.ident}::computed_value::T = value.into();
+                        % endif
                         style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
                     }
                 % endif
             % endfor
         }
     }
 
     /// Get an animatable value from a transition-property, an old style, and a
@@ -370,18 +378,18 @@ impl AnimatedProperty {
                                     new_style: &ComputedValues)
                                     -> AnimatedProperty {
         match *transition_property {
             TransitionProperty::All => panic!("Can't use TransitionProperty::All here."),
             % for prop in data.longhands:
                 % if prop.animatable:
                     TransitionProperty::${prop.camel_case} => {
                         AnimatedProperty::${prop.camel_case}(
-                            old_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}(),
-                            new_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}())
+                            old_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}().into(),
+                            new_style.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}().into())
                     }
                 % endif
             % endfor
             ref other => panic!("Can't use TransitionProperty::{:?} here", other),
         }
     }
 }
 
@@ -435,17 +443,17 @@ impl AnimationValue {
                         PropertyDeclaration::${prop.camel_case}(
                             % if prop.boxed:
                             Box::new(
                             % endif
                                 longhands::${prop.ident}::SpecifiedValue::from_computed_value(
                                 % if prop.is_animatable_with_computed_value:
                                     from
                                 % else:
-                                    &from.into()
+                                    &from.clone().into()
                                 % endif
                                 ))
                             % if prop.boxed:
                             )
                             % endif
                     }
                 % endif
             % endfor
@@ -467,17 +475,17 @@ impl AnimationValue {
                 if let Some(sf) = val.get_system() {
                     longhands::system_font::resolve_system_font(sf, context);
                 }
             % endif
                 Some(AnimationValue::${prop.camel_case}(
                 % if prop.is_animatable_with_computed_value:
                     val.to_computed_value(context)
                 % else:
-                    From::from(&val.to_computed_value(context))
+                    From::from(val.to_computed_value(context))
                 % endif
                 ))
             },
             % endif
             % endfor
             PropertyDeclaration::CSSWideKeyword(id, keyword) => {
                 match id {
                     // We put all the animatable properties first in the hopes
@@ -498,17 +506,17 @@ impl AnimationValue {
                             % endif
                             CSSWideKeyword::Inherit => {
                                 let inherit_struct = context.inherited_style
                                                             .get_${prop.style_struct.name_lower}();
                                 inherit_struct.clone_${prop.ident}()
                             },
                         };
                         % if not prop.is_animatable_with_computed_value:
-                            let computed = From::from(&computed);
+                            let computed = From::from(computed);
                         % endif
                         Some(AnimationValue::${prop.camel_case}(computed))
                     },
                     % endif
                     % endfor
                     % for prop in data.longhands:
                     % if not prop.animatable:
                     LonghandId::${prop.camel_case} => None,
@@ -565,18 +573,18 @@ impl AnimationValue {
             TransitionProperty::All => panic!("Can't use TransitionProperty::All here."),
             % for prop in data.longhands:
                 % if prop.animatable:
                     TransitionProperty::${prop.camel_case} => {
                         AnimationValue::${prop.camel_case}(
                         % if prop.is_animatable_with_computed_value:
                             computed_values.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}())
                         % else:
-                            From::from(&computed_values.get_${prop.style_struct.ident.strip("_")}()
-                                                                  .clone_${prop.ident}()))
+                            From::from(computed_values.get_${prop.style_struct.ident.strip("_")}()
+                                                                 .clone_${prop.ident}()))
                         % endif
                     }
                 % endif
             % endfor
             ref other => panic!("Can't use TransitionProperty::{:?} here.", other),
         }
     }
 }
@@ -931,106 +939,16 @@ impl Animatable for BackgroundSizeList {
     }
 
     #[inline]
     fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
         self.0.compute_squared_distance(&other.0)
     }
 }
 
-/// https://drafts.csswg.org/css-transitions/#animtype-color
-impl Animatable for RGBA {
-    #[inline]
-    fn add_weighted(&self, other: &RGBA, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
-        fn clamp(val: f32) -> f32 {
-            val.max(0.).min(1.)
-        }
-
-        let alpha = clamp(try!(self.alpha_f32().add_weighted(&other.alpha_f32(),
-                                                             self_portion, other_portion)));
-        if alpha == 0. {
-            Ok(RGBA::transparent())
-        } else {
-            // NB: We rely on RGBA::from_floats clamping already.
-            let red = try!((self.red_f32() * self.alpha_f32())
-                            .add_weighted(&(other.red_f32() * other.alpha_f32()),
-                                          self_portion, other_portion))
-                            * 1. / alpha;
-            let green = try!((self.green_f32() * self.alpha_f32())
-                             .add_weighted(&(other.green_f32() * other.alpha_f32()),
-                                           self_portion, other_portion))
-                             * 1. / alpha;
-            let blue = try!((self.blue_f32() * self.alpha_f32())
-                             .add_weighted(&(other.blue_f32() * other.alpha_f32()),
-                                           self_portion, other_portion))
-                             * 1. / alpha;
-            Ok(RGBA::from_floats(red, green, blue, alpha))
-        }
-    }
-
-    /// https://www.w3.org/TR/smil-animation/#animateColorElement says we should use Euclidean
-    /// RGB-cube distance.
-    #[inline]
-    fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
-        self.compute_squared_distance(other).map(|sd| sd.sqrt())
-    }
-
-    #[inline]
-    fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
-        fn clamp(val: f32) -> f32 {
-            val.max(0.).min(1.)
-        }
-
-        let start_a = clamp(self.alpha_f32());
-        let end_a = clamp(other.alpha_f32());
-        let start = [ start_a,
-                      self.red_f32() * start_a,
-                      self.green_f32() * start_a,
-                      self.blue_f32() * start_a ];
-        let end = [ end_a,
-                    other.red_f32() * end_a,
-                    other.green_f32() * end_a,
-                    other.blue_f32() * end_a ];
-        let diff = start.iter().zip(&end)
-                               .fold(0.0f64, |n, (&a, &b)| {
-                                   let diff = (a - b) as f64;
-                                   n + diff * diff
-                               });
-        Ok(diff)
-    }
-}
-
-/// https://drafts.csswg.org/css-transitions/#animtype-color
-impl Animatable for CSSParserColor {
-    #[inline]
-    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
-        match (*self, *other) {
-            (CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => {
-                this.add_weighted(other, self_portion, other_portion).map(CSSParserColor::RGBA)
-            }
-            _ => Err(()),
-        }
-    }
-
-    #[inline]
-    fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
-        self.compute_squared_distance(other).map(|sq| sq.sqrt())
-    }
-
-    #[inline]
-    fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
-        match (*self, *other) {
-            (CSSParserColor::RGBA(ref this), CSSParserColor::RGBA(ref other)) => {
-                this.compute_squared_distance(other)
-            },
-            _ => Ok(0.0),
-        }
-    }
-}
-
 /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
 impl Animatable for CalcLengthOrPercentage {
     #[inline]
     fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
         fn add_weighted_half<T>(this: Option<T>,
                                 other: Option<T>,
                                 self_portion: f64,
                                 other_portion: f64)
@@ -1564,19 +1482,16 @@ impl Animatable for ClipRect {
             result.extend(self.0.iter().cloned());
             result.extend(other.0.iter().cloned());
 
             Ok(${item}List(result))
         }
     }
 </%def>
 
-${impl_animatable_for_shadow('BoxShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
-${impl_animatable_for_shadow('TextShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
-
 /// Check if it's possible to do a direct numerical interpolation
 /// between these two transform lists.
 /// http://dev.w3.org/csswg/css-transforms/#transform-transform-animation
 fn can_interpolate_list(from_list: &[TransformOperation],
                         to_list: &[TransformOperation]) -> bool {
     // Lists must be equal length
     if from_list.len() != to_list.len() {
         return false;
@@ -2621,28 +2536,28 @@ impl<T, U> Animatable for Either<T, U>
             (&Either::Second(ref this), &Either::Second(ref other)) => {
                 this.compute_squared_distance(other)
             },
             _ => Err(())
         }
     }
 }
 
-impl <'a> From<<&'a IntermediateRGBA> for RGBA {
-    fn from(extended_rgba: &IntermediateRGBA) -> RGBA {
+impl From<IntermediateRGBA> for RGBA {
+    fn from(extended_rgba: IntermediateRGBA) -> RGBA {
         // RGBA::from_floats clamps each component values.
         RGBA::from_floats(extended_rgba.red,
                           extended_rgba.green,
                           extended_rgba.blue,
                           extended_rgba.alpha)
     }
 }
 
-impl <'a> From<<&'a RGBA> for IntermediateRGBA {
-    fn from(rgba: &RGBA) -> IntermediateRGBA {
+impl From<RGBA> for IntermediateRGBA {
+    fn from(rgba: RGBA) -> IntermediateRGBA {
         IntermediateRGBA::new(rgba.red_f32(),
                               rgba.green_f32(),
                               rgba.blue_f32(),
                               rgba.alpha_f32())
     }
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
@@ -2720,41 +2635,41 @@ impl Animatable for IntermediateRGBA {
                                .fold(0.0f64, |n, (&a, &b)| {
                                    let diff = (a - b) as f64;
                                    n + diff * diff
                                });
         Ok(diff)
     }
 }
 
-impl<'a> From<<&'a Either<CSSParserColor, Auto>> for Either<IntermediateColor, Auto> {
-    fn from(from: &Either<CSSParserColor, Auto>) -> Either<IntermediateColor, Auto> {
-        match *from {
-            Either::First(ref from) =>
-                match *from {
-                    CSSParserColor::RGBA(ref color) =>
+impl From<Either<CSSParserColor, Auto>> for Either<IntermediateColor, Auto> {
+    fn from(from: Either<CSSParserColor, Auto>) -> Either<IntermediateColor, Auto> {
+        match from {
+            Either::First(from) =>
+                match from {
+                    CSSParserColor::RGBA(color) =>
                         Either::First(IntermediateColor::IntermediateRGBA(
                             IntermediateRGBA::new(color.red_f32(),
                                                   color.green_f32(),
                                                   color.blue_f32(),
                                                   color.alpha_f32()))),
                     CSSParserColor::CurrentColor =>
                         Either::First(IntermediateColor::CurrentColor),
                 },
             Either::Second(Auto) => Either::Second(Auto),
         }
     }
 }
 
-impl<'a> From<<&'a Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> {
-    fn from(from: &Either<IntermediateColor, Auto>) -> Either<CSSParserColor, Auto> {
-        match *from {
-            Either::First(ref from) =>
-                match *from {
-                    IntermediateColor::IntermediateRGBA(ref color) =>
+impl From<Either<IntermediateColor, Auto>> for Either<CSSParserColor, Auto> {
+    fn from(from: Either<IntermediateColor, Auto>) -> Either<CSSParserColor, Auto> {
+        match from {
+            Either::First(from) =>
+                match from {
+                    IntermediateColor::IntermediateRGBA(color) =>
                         Either::First(CSSParserColor::RGBA(RGBA::from_floats(color.red,
                                                                              color.green,
                                                                              color.blue,
                                                                              color.alpha))),
                     IntermediateColor::CurrentColor =>
                         Either::First(CSSParserColor::CurrentColor),
                 },
             Either::Second(Auto) => Either::Second(Auto),
@@ -2795,33 +2710,33 @@ impl Animatable for IntermediateColor {
             (IntermediateColor::IntermediateRGBA(ref this), IntermediateColor::IntermediateRGBA(ref other)) => {
                 this.compute_squared_distance(other)
             },
             _ => Ok(0.0),
         }
     }
 }
 
-impl <'a> From<<&'a CSSParserColor> for IntermediateColor {
-    fn from(color: &CSSParserColor) -> IntermediateColor {
-        match *color {
-            CSSParserColor::RGBA(ref color) =>
+impl From<CSSParserColor> for IntermediateColor {
+    fn from(color: CSSParserColor) -> IntermediateColor {
+        match color {
+            CSSParserColor::RGBA(color) =>
                 IntermediateColor::IntermediateRGBA(IntermediateRGBA::new(color.red_f32(),
                                                                           color.green_f32(),
                                                                           color.blue_f32(),
                                                                           color.alpha_f32())),
             CSSParserColor::CurrentColor => IntermediateColor::CurrentColor,
         }
     }
 }
 
-impl <'a> From<<&'a IntermediateColor> for CSSParserColor {
-    fn from(color: &IntermediateColor) -> CSSParserColor {
-        match *color {
-            IntermediateColor::IntermediateRGBA(ref color) =>
+impl From<IntermediateColor> for CSSParserColor {
+    fn from(color: IntermediateColor) -> CSSParserColor {
+        match color {
+            IntermediateColor::IntermediateRGBA(color) =>
                 CSSParserColor::RGBA(RGBA::from_floats(color.red,
                                                        color.green,
                                                        color.blue,
                                                        color.alpha)),
             IntermediateColor::CurrentColor => CSSParserColor::CurrentColor,
         }
     }
 }
@@ -2845,50 +2760,50 @@ impl <'a> From<<&'a IntermediateColor> f
     }
 
     #[derive(Clone, Debug, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     #[allow(missing_docs)]
     /// Intermediate type for box-shadow list and text-shadow list.
     pub struct Intermediate${type}ShadowList(pub SmallVec<[Intermediate${type}Shadow; 1]>);
 
-    impl <'a> From<<&'a Intermediate${type}ShadowList> for ${type}ShadowList {
-        fn from(shadow_list: &Intermediate${type}ShadowList) -> ${type}ShadowList {
-            ${type}ShadowList(shadow_list.0.iter().map(|s| s.into()).collect())
+    impl From<Intermediate${type}ShadowList> for ${type}ShadowList {
+        fn from(shadow_list: Intermediate${type}ShadowList) -> ${type}ShadowList {
+            ${type}ShadowList(shadow_list.0.into_iter().map(|s| s.into()).collect())
         }
     }
 
-    impl <'a> From<<&'a ${type}ShadowList> for Intermediate${type}ShadowList {
-        fn from(shadow_list: &${type}ShadowList) -> Intermediate${type}ShadowList {
-            Intermediate${type}ShadowList(shadow_list.0.iter().map(|s| s.into()).collect())
+    impl From<${type}ShadowList> for Intermediate${type}ShadowList {
+        fn from(shadow_list: ${type}ShadowList) -> Intermediate${type}ShadowList {
+            Intermediate${type}ShadowList(shadow_list.0.into_iter().map(|s| s.into()).collect())
         }
     }
 
-    impl <'a> From<<&'a Intermediate${type}Shadow> for ${type}Shadow {
-        fn from(shadow: &Intermediate${type}Shadow) -> ${type}Shadow {
+    impl From<Intermediate${type}Shadow> for ${type}Shadow {
+        fn from(shadow: Intermediate${type}Shadow) -> ${type}Shadow {
             ${type}Shadow {
                 offset_x: shadow.offset_x,
                 offset_y: shadow.offset_y,
                 blur_radius: shadow.blur_radius,
-                color: (&shadow.color).into(),
+                color: shadow.color.into(),
                 % if type == "Box":
                 spread_radius: shadow.spread_radius,
                 inset: shadow.inset,
                 % endif
             }
         }
     }
 
-    impl <'a> From<<&'a ${type}Shadow> for Intermediate${type}Shadow {
-        fn from(shadow: &${type}Shadow) -> Intermediate${type}Shadow {
+    impl From<${type}Shadow> for Intermediate${type}Shadow {
+        fn from(shadow: ${type}Shadow) -> Intermediate${type}Shadow {
             Intermediate${type}Shadow {
                 offset_x: shadow.offset_x,
                 offset_y: shadow.offset_y,
                 blur_radius: shadow.blur_radius,
-                color: (&shadow.color).into(),
+                color: shadow.color.into(),
                 % if type == "Box":
                 spread_radius: shadow.spread_radius,
                 inset: shadow.inset,
                 % endif
             }
         }
     }
     ${impl_animatable_for_shadow('Intermediate%sShadow' % type,
--- a/servo/tests/unit/style/animated_properties.rs
+++ b/servo/tests/unit/style/animated_properties.rs
@@ -1,50 +1,56 @@
 /* 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::Animatable;
+use cssparser::RGBA;
+use style::properties::animated_properties::{Animatable, IntermediateRGBA};
+
+fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
+    let from: IntermediateRGBA = from.into();
+    let to: IntermediateRGBA = to.into();
+    from.interpolate(&to, progress).unwrap().into()
+}
 
 #[test]
 fn test_rgba_color_interepolation_preserves_transparent() {
-    assert_eq!(Color::RGBA(RGBA::transparent())
-                .interpolate(&Color::RGBA(RGBA::transparent()), 0.5).unwrap(),
-               Color::RGBA(RGBA::transparent()));
+    assert_eq!(interpolate_rgba(RGBA::transparent(),
+                                RGBA::transparent(), 0.5),
+               RGBA::transparent());
 }
 
 #[test]
 fn test_rgba_color_interepolation_alpha() {
-    assert_eq!(Color::RGBA(RGBA::new(200, 0, 0, 100))
-                .interpolate(&Color::RGBA(RGBA::new(0, 200, 0, 200)), 0.5).unwrap(),
-               Color::RGBA(RGBA::new(67, 133, 0, 150)));
+    assert_eq!(interpolate_rgba(RGBA::new(200, 0, 0, 100),
+                                RGBA::new(0, 200, 0, 200), 0.5),
+               RGBA::new(67, 133, 0, 150));
 }
 
 #[test]
 fn test_rgba_color_interepolation_out_of_range_1() {
     // Some cubic-bezier functions produce values that are out of range [0, 1].
     // Unclamped cases.
-    assert_eq!(Color::RGBA(RGBA::from_floats(0.3, 0.0, 0.0, 0.4)).interpolate(
-              &Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.6)), -0.5).unwrap(),
-               Color::RGBA(RGBA::new(154, 0, 0, 77)));
+    assert_eq!(interpolate_rgba(RGBA::from_floats(0.3, 0.0, 0.0, 0.4),
+                                RGBA::from_floats(0.0, 1.0, 0.0, 0.6), -0.5),
+               RGBA::new(154, 0, 0, 77));
 }
 
 #[test]
 fn test_rgba_color_interepolation_out_of_range_2() {
-    assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.6)).interpolate(
-              &Color::RGBA(RGBA::from_floats(0.0, 0.3, 0.0, 0.4)), 1.5).unwrap(),
-               Color::RGBA(RGBA::new(0, 154, 0, 77)));
+    assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.6),
+                                RGBA::from_floats(0.0, 0.3, 0.0, 0.4), 1.5),
+               RGBA::new(0, 154, 0, 77));
 }
 
 #[test]
 fn test_rgba_color_interepolation_out_of_range_clamped_1() {
-    assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.8)).interpolate(
-              &Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.2)), -0.5).unwrap(),
-               Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 1.0)));
+    assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
+                                RGBA::from_floats(0.0, 1.0, 0.0, 0.2), -0.5),
+               RGBA::from_floats(1.0, 0.0, 0.0, 1.0));
 }
 
 #[test]
 fn test_rgba_color_interepolation_out_of_range_clamped_2() {
-    assert_eq!(Color::RGBA(RGBA::from_floats(1.0, 0.0, 0.0, 0.8)).interpolate(
-              &Color::RGBA(RGBA::from_floats(0.0, 1.0, 0.0, 0.2)), 1.5).unwrap(),
-               Color::RGBA(RGBA::from_floats(0.0, 0.0, 0.0, 0.0)));
+    assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
+                                RGBA::from_floats(0.0, 1.0, 0.0, 0.2), 1.5),
+               RGBA::from_floats(0.0, 0.0, 0.0, 0.0));
 }