Bug 1455358: Fix clamping on animations. r?xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 19 Apr 2018 21:40:25 +0200
changeset 785221 4c82661a9b5449543cb477042322d81b15bcae0d
parent 785220 103c26e044c0e36cded06d0300fc30b4de075216
child 785222 db8179809dae9cbcfa80f145acac95bc59ed58c1
push id107172
push userbmo:emilio@crisal.io
push dateThu, 19 Apr 2018 20:11:15 +0000
reviewersxidorn
bugs1455358
milestone61.0a1
Bug 1455358: Fix clamping on animations. r?xidorn MozReview-Commit-ID: Awyub0dMOmq
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/values/computed/angle.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/specified/angle.rs
servo/components/style/values/specified/font.rs
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -15,18 +15,17 @@
                           spec="https://drafts.csswg.org/css-fonts/#propdef-font-family",
                           servo_restyle_damage="rebuild_and_reflow")}
 
 ${helpers.predefined_type(
     "font-style",
     "FontStyle",
     initial_value="computed::FontStyle::normal()",
     initial_specified_value="specified::FontStyle::normal()",
-    # FIXME(emilio): This won't handle clamping correctly.
-    animation_value_type="ComputedValue",
+    animation_value_type="FontStyle",
     flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
     spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
     servo_restyle_damage="rebuild_and_reflow",
 )}
 
 <% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
                                       "all-small-caps": "ALLSMALL",
                                       "petite-caps": "PETITECAPS",
--- a/servo/components/style/values/computed/angle.rs
+++ b/servo/components/style/values/computed/angle.rs
@@ -59,16 +59,22 @@ impl Angle {
             Angle::Deg(val) => val as f64 * RAD_PER_DEG,
             Angle::Grad(val) => val as f64 * RAD_PER_GRAD,
             Angle::Turn(val) => val as f64 * RAD_PER_TURN,
             Angle::Rad(val) => val as f64,
         };
         radians.min(f64::MAX).max(f64::MIN)
     }
 
+    /// Return the value in degrees.
+    pub fn degrees(&self) -> f32 {
+        use std::f32::consts::PI;
+        self.radians() * 360. / (2. * PI)
+    }
+
     /// <https://drafts.csswg.org/css-transitions/#animtype-number>
     #[inline]
     fn animate_fallback(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
         Ok(Angle::from_radians(self.radians().animate(&other.radians(), procedure)?))
     }
 }
 
 impl AsRef<Angle> for Angle {
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -825,35 +825,58 @@ impl ToComputedValue for specified::MozS
         cmp::min(int, i8::MAX as i32) as i8
     }
 
     fn from_computed_value(other: &i8) -> Self {
         specified::MozScriptLevel::MozAbsolute(*other as i32)
     }
 }
 
+/// A wrapper over an `Angle`, that handles clamping to the appropriate range
+/// for `font-style` animation.
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)]
+pub struct FontStyleAngle(pub Angle);
+
+impl ToAnimatedValue for FontStyleAngle {
+    type AnimatedValue = Angle;
+
+    #[inline]
+    fn to_animated_value(self) -> Self::AnimatedValue {
+        self.0
+    }
+
+    #[inline]
+    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
+        FontStyleAngle(Angle::Deg(
+            animated.degrees()
+                .min(specified::FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES)
+                .max(specified::FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES)
+        ))
+    }
+}
+
 /// The computed value of `font-style`.
 ///
 /// FIXME(emilio): Angle should be a custom type to handle clamping during
 /// animation.
-pub type FontStyle = generics::FontStyle<Angle>;
+pub type FontStyle = generics::FontStyle<FontStyleAngle>;
 
 impl FontStyle {
     /// The `normal` value.
     #[inline]
     pub fn normal() -> Self {
         generics::FontStyle::Normal
     }
 
     /// The default angle for font-style: oblique. This is 20deg per spec:
     ///
     /// https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
     #[inline]
-    pub fn default_angle() -> Angle {
-        Angle::Deg(specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES)
+    fn default_angle() -> FontStyleAngle {
+        FontStyleAngle(Angle::Deg(specified::DEFAULT_FONT_STYLE_OBLIQUE_ANGLE_DEGREES))
     }
 
 
     /// Get the font style from Gecko's nsFont struct.
     #[cfg(feature = "gecko")]
     pub fn from_gecko(kw: u8) -> Self {
         use gecko_bindings::structs;
 
--- a/servo/components/style/values/specified/angle.rs
+++ b/servo/components/style/values/specified/angle.rs
@@ -105,18 +105,17 @@ impl Angle {
     #[inline]
     pub fn radians(self) -> f32 {
         self.value.radians()
     }
 
     /// Returns the amount of degrees this angle represents.
     #[inline]
     pub fn degrees(self) -> f32 {
-        use std::f32::consts::PI;
-        self.radians() * 360. / (2. * PI)
+        self.value.degrees()
     }
 
     /// Returns `0deg`.
     pub fn zero() -> Self {
         Self::from_degrees(0.0, false)
     }
 
     /// Returns an `Angle` parsed from a `calc()` expression.
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -14,17 +14,17 @@ use gecko_bindings::bindings;
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use parser::{Parse, ParserContext};
 use properties::longhands::system_font::SystemFont;
 use std::fmt::{self, Write};
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 use values::CustomIdent;
 use values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage};
 use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
-use values::computed::font::{FamilyName, FontFamilyList, SingleFontFamily};
+use values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily};
 use values::generics::NonNegative;
 use values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
 use values::generics::font::{KeywordInfo as GenericKeywordInfo, KeywordSize, VariationValue};
 use values::specified::{AllowQuirks, Angle, Integer, LengthOrPercentage, NoCalcLength, Number, Percentage};
 use values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
 
 const DEFAULT_SCRIPT_MIN_SIZE_PT: u32 = 8;
 const DEFAULT_SCRIPT_SIZE_MULTIPLIER: f64 = 0.71;
@@ -236,27 +236,27 @@ impl Parse for SpecifiedFontStyle {
 impl ToComputedValue for SpecifiedFontStyle {
     type ComputedValue = computed::FontStyle;
 
     fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
         match *self {
             generics::FontStyle::Normal => generics::FontStyle::Normal,
             generics::FontStyle::Italic => generics::FontStyle::Italic,
             generics::FontStyle::Oblique(ref angle) => {
-                generics::FontStyle::Oblique(Self::compute_angle(angle))
+                generics::FontStyle::Oblique(FontStyleAngle(Self::compute_angle(angle)))
             }
         }
     }
 
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         match *computed {
             generics::FontStyle::Normal => generics::FontStyle::Normal,
             generics::FontStyle::Italic => generics::FontStyle::Italic,
             generics::FontStyle::Oblique(ref angle) => {
-                generics::FontStyle::Oblique(Angle::from_computed_value(angle))
+                generics::FontStyle::Oblique(Angle::from_computed_value(&angle.0))
             }
         }
     }
 }
 
 
 /// The default angle for `font-style: oblique`.
 ///