servo: Merge #17180 - stylo: Animate fill and stroke (from Manishearth:stylo-fill-stroke); r=birtles
authorManish Goregaokar <manishearth@gmail.com>
Tue, 06 Jun 2017 00:12:51 -0700
changeset 410602 6fd241d76d91d16eb5a3416c7c3299d8744d325d
parent 410601 b98f9c21f6c76f7717213a7f1300b78aa9dde6e4
child 410603 e843dab00aa729cba50201b31011a8b50f4c4e29
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs17180, 1369277
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 #17180 - stylo: Animate fill and stroke (from Manishearth:stylo-fill-stroke); r=birtles r=birtles https://bugzilla.mozilla.org/show_bug.cgi?id=1369277 Source-Repo: https://github.com/servo/servo Source-Revision: 2da8eb0342f6701b5365116b96113c83a1599b1f
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/inherited_svg.mako.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -456,16 +456,45 @@ fn color_to_nscolor_zero_currentcolor(co
     pub fn copy_${ident}_from(&mut self, other: &Self) {
         unsafe {
             bindings::Gecko_nsStyleSVGPaint_CopyFrom(
                 &mut ${get_gecko_property(gecko_ffi_name)},
                 & ${get_gecko_property(gecko_ffi_name, "other")}
             );
         }
     }
+
+    #[allow(non_snake_case)]
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
+        use values::generics::{SVGPaint, SVGPaintKind};
+        use self::structs::nsStyleSVGPaintType;
+        use self::structs::nsStyleSVGFallbackType;
+        let ref paint = ${get_gecko_property(gecko_ffi_name)};
+        let fallback = if let nsStyleSVGFallbackType::eStyleSVGFallbackType_Color = paint.mFallbackType {
+            Some(Color::RGBA(convert_nscolor_to_rgba(paint.mFallbackColor)))
+        } else {
+            None
+        };
+        let kind = match paint.mType {
+            nsStyleSVGPaintType::eStyleSVGPaintType_None => SVGPaintKind::None,
+            nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill => SVGPaintKind::ContextFill,
+            nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke,
+            nsStyleSVGPaintType::eStyleSVGPaintType_Server => {
+                // FIXME (bug 1353966) this should animate
+                SVGPaintKind::None
+            }
+            nsStyleSVGPaintType::eStyleSVGPaintType_Color => {
+                unsafe { SVGPaintKind::Color(Color::RGBA(convert_nscolor_to_rgba(*paint.mPaint.mColor.as_ref()))) }
+            }
+        };
+        SVGPaint {
+            kind: kind,
+            fallback: fallback,
+        }
+    }
 </%def>
 
 <%def name="impl_app_units(ident, gecko_ffi_name, need_clone, inherit_from=None, round_to_pixels=False)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         let value = {
             % if round_to_pixels:
             let au_per_device_px = Au(self.gecko.mTwipsPerPixel);
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -37,16 +37,17 @@ use style_traits::ToCss;
 use super::ComputedValues;
 use values::CSSFloat;
 use values::{Auto, Either};
 use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
 use values::computed::{BorderCornerRadius, ClipRect};
 use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
 use values::computed::{MaxLength, MozLength};
 use values::computed::ToComputedValue;
+use values::generics::{SVGPaint, SVGPaintKind};
 use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
 use values::generics::position as generic_position;
 
 
 /// A given transition property, that is either `All`, or an animatable
 /// property.
 // NB: This needs to be here because it needs all the longhands generated
 // beforehand.
@@ -2844,16 +2845,85 @@ impl From<IntermediateColor> for CSSPars
                                                        color.green,
                                                        color.blue,
                                                        color.alpha)),
             IntermediateColor::CurrentColor => CSSParserColor::CurrentColor,
         }
     }
 }
 
+/// Animatable SVGPaint
+pub type IntermediateSVGPaint = SVGPaint<IntermediateColor>;
+/// Animatable SVGPaintKind
+pub type IntermediateSVGPaintKind = SVGPaintKind<IntermediateColor>;
+
+impl From<::values::computed::SVGPaint> for IntermediateSVGPaint {
+    fn from(paint: ::values::computed::SVGPaint) -> IntermediateSVGPaint {
+        paint.convert(|color| (*color).into())
+    }
+}
+
+impl From<IntermediateSVGPaint> for ::values::computed::SVGPaint {
+    fn from(paint: IntermediateSVGPaint) -> ::values::computed::SVGPaint {
+        paint.convert(|color| (*color).into())
+    }
+}
+
+
+impl Animatable for IntermediateSVGPaint {
+    #[inline]
+    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
+        Ok(IntermediateSVGPaint {
+            kind: self.kind.add_weighted(&other.kind, self_portion, other_portion)?,
+            fallback: self.fallback.add_weighted(&other.fallback, self_portion, other_portion)?,
+        })
+    }
+
+    #[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, ()> {
+        Ok(self.kind.compute_squared_distance(&other.kind)? +
+            self.fallback.compute_squared_distance(&other.fallback)?)
+    }
+}
+
+impl Animatable for IntermediateSVGPaintKind {
+    #[inline]
+    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
+        match (self, other) {
+            (&SVGPaintKind::Color(ref self_color), &SVGPaintKind::Color(ref other_color)) => {
+                Ok(SVGPaintKind::Color(self_color.add_weighted(other_color, self_portion, other_portion)?))
+            }
+            // FIXME context values should be interpolable with colors
+            // Gecko doesn't implement this behavior either.
+            (&SVGPaintKind::None, &SVGPaintKind::None) => Ok(SVGPaintKind::None),
+            (&SVGPaintKind::ContextFill, &SVGPaintKind::ContextFill) => Ok(SVGPaintKind::ContextFill),
+            (&SVGPaintKind::ContextStroke, &SVGPaintKind::ContextStroke) => Ok(SVGPaintKind::ContextStroke),
+            _ => Err(())
+        }
+    }
+
+    #[inline]
+    fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
+        match (self, other) {
+            (&SVGPaintKind::Color(ref self_color), &SVGPaintKind::Color(ref other_color)) => {
+                self_color.compute_distance(other_color)
+            }
+            (&SVGPaintKind::None, &SVGPaintKind::None) |
+            (&SVGPaintKind::ContextFill, &SVGPaintKind::ContextFill) |
+            (&SVGPaintKind::ContextStroke, &SVGPaintKind::ContextStroke)=> Ok(0.0),
+            _ => Err(())
+        }
+    }
+}
+
 <%def name="impl_intermediate_type_for_shadow(type)">
     #[derive(Copy, Clone, Debug, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     #[allow(missing_docs)]
     /// Intermediate type for box-shadow and text-shadow.
     /// The difference between normal shadow type is that this type uses
     /// IntermediateColor instead of ParserColor.
     pub struct Intermediate${type}Shadow {
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -30,17 +30,17 @@
                          gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
                          animation_value_type="discrete",
                          spec="https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationFiltersProperty")}
 
 ${helpers.predefined_type(
     "fill", "SVGPaint",
     "::values::computed::SVGPaint::black()",
     products="gecko",
-    animation_value_type="none",
+    animation_value_type="IntermediateSVGPaint",
     boxed=True,
     spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingFillPaint")}
 
 ${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
                           products="gecko", animation_value_type="none",
                           spec="https://www.w3.org/TR/SVG11/painting.html#FillOpacityProperty")}
 
 ${helpers.single_keyword("fill-rule", "nonzero evenodd",
@@ -54,17 +54,17 @@
                          products="gecko",
                          animation_value_type="discrete",
                          spec="https://www.w3.org/TR/SVG11/painting.html#ShapeRenderingProperty")}
 
 ${helpers.predefined_type(
     "stroke", "SVGPaint",
     "Default::default()",
     products="gecko",
-    animation_value_type="none",
+    animation_value_type="IntermediateSVGPaint",
     boxed=True,
     spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")}
 
 ${helpers.predefined_type(
     "stroke-width", "LengthOrPercentageOrNumber",
     "Either::First(1.0)",
     "parse_non_negative",
     products="gecko",