Bug 1353202 - Support additive animation of font-stretch draft
authorBrian Birtles <birtles@gmail.com>
Tue, 23 May 2017 14:57:07 +0900
changeset 582819 0b828217edea9e1118e04a178d40aa5ad0cae174
parent 582812 52ad060326bafda3eadc0539f65a6b098608538d
child 582820 47af1de5bb11ae3f7af7311891137444cb6a564c
push id60187
push userbbirtles@mozilla.com
push dateTue, 23 May 2017 05:57:34 +0000
bugs1353202, 1363246, 1304886
milestone55.0a1
Bug 1353202 - Support additive animation of font-stretch Although there are no specific tests for this yet (that's bug 1363246), if any code does try to perform addition or accumulation with a font-stretch value (e.g. dom/animation/test/crashtests/1304886-1.html) it will likely fail the bounds check in the Into trait. To avoid that, this patch provides an basic implementation of add_weighted for font-stretch that should work correctly with portions whose sum is outside the [0.0, 1.0] range. MozReview-Commit-ID: 2tNMOh9HyP0
servo/components/style/properties/helpers/animated_properties.mako.rs
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1368,21 +1368,26 @@ impl Animatable for FontWeight {
         let b = (*other as u32) as f64;
         a.compute_distance(&b)
     }
 }
 
 /// https://drafts.csswg.org/css-fonts/#font-stretch-prop
 impl Animatable for FontStretch {
     #[inline]
-    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
+    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
+        -> Result<Self, ()>
+    {
         let from = f64::from(*self);
-        let to   = f64::from(*other);
-        let interpolated_mapped_index = ((from * self_portion + to * other_portion) + 0.5).floor();
-        Ok(interpolated_mapped_index.into())
+        let to = f64::from(*other);
+        // FIXME: When `const fn` is available in release rust, make |normal|, below, const.
+        let normal = f64::from(FontStretch::normal);
+        let result = (from - normal) * self_portion + (to - normal) * other_portion + normal;
+
+        Ok(result.into())
     }
 
     #[inline]
     fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
         let from = f64::from(*self);
         let to   = f64::from(*other);
         from.compute_distance(&to)
     }
@@ -1405,21 +1410,21 @@ impl From<FontStretch> for f64 {
             ultra_expanded  => 9.0,
         }
     }
 }
 
 impl Into<FontStretch> for f64 {
     fn into(self) -> FontStretch {
         use properties::longhands::font_stretch::computed_value::T::*;
-        debug_assert!(self >= 1.0 && self <= 9.0);
+        let index = (self + 0.5).floor().min(9.0).max(1.0);
         static FONT_STRETCH_ENUM_MAP: [FontStretch; 9] =
             [ ultra_condensed, extra_condensed, condensed, semi_condensed, normal,
               semi_expanded, expanded, extra_expanded, ultra_expanded ];
-        FONT_STRETCH_ENUM_MAP[(self - 1.0) as usize]
+        FONT_STRETCH_ENUM_MAP[(index - 1.0) as usize]
     }
 }
 
 /// https://drafts.csswg.org/css-transitions/#animtype-simple-list
 impl<H: Animatable, V: Animatable> Animatable for generic_position::Position<H, V> {
     #[inline]
     fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
         Ok(generic_position::Position {