Bug 1356941 - Introduce a macro to implement Interpolate trait for box-shadow and text-shadow. r?birtles draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Mon, 24 Apr 2017 15:03:43 +0900
changeset 566927 0f02ffb133d807a4056142b61ad82d93a4dac08f
parent 566926 5777cee1f46f6e3027844fb2a82a43674208a9fe
child 566928 172daca0e71f9379a550b1b0e7434dc08d508850
push id55379
push userhikezoe@mozilla.com
push dateMon, 24 Apr 2017 06:04:15 +0000
reviewersbirtles
bugs1356941
milestone55.0a1
Bug 1356941 - Introduce a macro to implement Interpolate trait for box-shadow and text-shadow. r?birtles This macro will be used for implementation of intermediate type shadows as well. In the case of intermediate types transparent_color will be IntermediateRGB::transparent(). MozReview-Commit-ID: 2HGwLQoS72I
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
@@ -997,124 +997,99 @@ impl Interpolate for ClipRect {
             top: try!(self.top.interpolate(&other.top, time)),
             right: try!(self.right.interpolate(&other.right, time)),
             bottom: try!(self.bottom.interpolate(&other.bottom, time)),
             left: try!(self.left.interpolate(&other.left, time)),
         })
     }
 }
 
-/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
-impl Interpolate for TextShadow {
-    #[inline]
-    fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
-        Ok(TextShadow {
-            offset_x: try!(self.offset_x.interpolate(&other.offset_x, progress)),
-            offset_y: try!(self.offset_y.interpolate(&other.offset_y, progress)),
-            blur_radius: try!(self.blur_radius.interpolate(&other.blur_radius, progress)),
-            color: try!(self.color.interpolate(&other.color, progress)),
-        })
-    }
-}
+<%def name="impl_interpolate_for_shadow(item, transparent_color)">
+    impl Interpolate for ${item} {
+        #[inline]
+        fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
+            % if "Box" in item:
+            // It can't be interpolated if inset does not match.
+            if self.inset != other.inset {
+                return Err(());
+            }
+            % endif
 
-/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
-impl Interpolate for TextShadowList {
-    #[inline]
-    fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
-        let zero = TextShadow {
-            offset_x: Au(0),
-            offset_y: Au(0),
-            blur_radius: Au(0),
-            color: CSSParserColor::RGBA(RGBA::transparent()),
-        };
-
-        let max_len = cmp::max(self.0.len(), other.0.len());
-        let mut result = Vec::with_capacity(max_len);
+            let x = try!(self.offset_x.interpolate(&other.offset_x, progress));
+            let y = try!(self.offset_y.interpolate(&other.offset_y, progress));
+            let color = try!(self.color.interpolate(&other.color, progress));
+            let blur = try!(self.blur_radius.interpolate(&other.blur_radius, progress));
+            % if "Box" in item:
+            let spread = try!(self.spread_radius.interpolate(&other.spread_radius, progress));
+            % endif
 
-        for i in 0..max_len {
-            let shadow = match (self.0.get(i), other.0.get(i)) {
-                (Some(shadow), Some(other))
-                    => try!(shadow.interpolate(other, progress)),
-                (Some(shadow), None) => {
-                    shadow.interpolate(&zero, progress).unwrap()
-                }
-                (None, Some(shadow)) => {
-                    zero.interpolate(&shadow, progress).unwrap()
-                }
-                (None, None) => unreachable!(),
-            };
-            result.push(shadow);
+            Ok(${item} {
+                offset_x: x,
+                offset_y: y,
+                blur_radius: blur,
+                color: color,
+                % if "Box" in item:
+                spread_radius: spread,
+                inset: self.inset,
+                % endif
+            })
         }
-
-        Ok(TextShadowList(result))
     }
-}
-
 
-impl Interpolate for BoxShadowList {
-    #[inline]
-    fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
-        // The inset value must change
-        let mut zero = BoxShadow {
-            offset_x: Au(0),
-            offset_y: Au(0),
-            spread_radius: Au(0),
-            blur_radius: Au(0),
-            color: CSSParserColor::RGBA(RGBA::transparent()),
-            inset: false,
-        };
-
-        let max_len = cmp::max(self.0.len(), other.0.len());
-        let mut result = Vec::with_capacity(max_len);
-
-        for i in 0..max_len {
-            let shadow = match (self.0.get(i), other.0.get(i)) {
-                (Some(shadow), Some(other))
-                    => try!(shadow.interpolate(other, progress)),
-                (Some(shadow), None) => {
-                    zero.inset = shadow.inset;
-                    shadow.interpolate(&zero, progress).unwrap()
-                }
-                (None, Some(shadow)) => {
-                    zero.inset = shadow.inset;
-                    zero.interpolate(&shadow, progress).unwrap()
-                }
-                (None, None) => unreachable!(),
+    /// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
+    impl Interpolate for ${item}List {
+        #[inline]
+        fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
+            // The inset value must change
+            % if "Box" in item:
+            let mut zero = ${item} {
+            % else:
+            let zero = ${item} {
+            % endif
+                offset_x: Au(0),
+                offset_y: Au(0),
+                blur_radius: Au(0),
+                color: ${transparent_color},
+                % if "Box" in item:
+                spread_radius: Au(0),
+                inset: false,
+                % endif
             };
-            result.push(shadow);
-        }
 
-        Ok(BoxShadowList(result))
-    }
-}
-
-/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
-impl Interpolate for BoxShadow {
-    #[inline]
-    fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
-        if self.inset != other.inset {
-            return Err(());
-        }
+            let max_len = cmp::max(self.0.len(), other.0.len());
+            let mut result = Vec::with_capacity(max_len);
 
-        let x = try!(self.offset_x.interpolate(&other.offset_x, progress));
-        let y = try!(self.offset_y.interpolate(&other.offset_y, progress));
-        let color = try!(self.color.interpolate(&other.color, progress));
-        let spread = try!(self.spread_radius.interpolate(&other.spread_radius, progress));
-        let blur = try!(self.blur_radius.interpolate(&other.blur_radius, progress));
+            for i in 0..max_len {
+                let shadow = match (self.0.get(i), other.0.get(i)) {
+                    (Some(shadow), Some(other))
+                        => try!(shadow.interpolate(other, progress)),
+                    (Some(shadow), None) => {
+                        % if "Box" in item:
+                        zero.inset = shadow.inset;
+                        % endif
+                        shadow.interpolate(&zero, progress).unwrap()
+                    }
+                    (None, Some(shadow)) => {
+                        % if "Box" in item:
+                        zero.inset = shadow.inset;
+                        % endif
+                        zero.interpolate(&shadow, progress).unwrap()
+                    }
+                    (None, None) => unreachable!(),
+                };
+                result.push(shadow);
+            }
 
-        Ok(BoxShadow {
-            offset_x: x,
-            offset_y: y,
-            blur_radius: blur,
-            spread_radius: spread,
-            color: color,
-            inset: self.inset,
-        })
+            Ok(${item}List(result))
+        }
     }
-}
+</%def>
+
+${impl_interpolate_for_shadow('BoxShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
+${impl_interpolate_for_shadow('TextShadow', 'CSSParserColor::RGBA(RGBA::transparent())',)}
 
 impl Interpolate for LengthOrNone {
     fn interpolate(&self, other: &Self, progress: f64) -> Result<Self, ()> {
         match (*self, *other) {
             (Either::First(ref length), Either::First(ref other)) =>
                 length.interpolate(&other, progress).map(Either::First),
             _ => Err(()),
         }