Bug 1367283 - Part 2: Implements background related properties. r?hiro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Mon, 29 May 2017 15:50:09 +0900
changeset 585864 fdcb0dbd60d9fd0963adac74987fd5afee4b198d
parent 585863 fca77161616c6f69347bbf0e069d3a967cdf7f41
child 585865 c806fdf22d2a77fe787f04bff20876c3a146c353
push id61214
push userbmo:dakatsuka@mozilla.com
push dateMon, 29 May 2017 06:57:32 +0000
reviewershiro
bugs1367283
milestone55.0a1
Bug 1367283 - Part 2: Implements background related properties. r?hiro In this patch, implements following background related properties that type is single keyword. * background-attachment * background-clip * background-origin * background-blend-mode MozReview-Commit-ID: 95FXL6LTaVE
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/background.mako.rs
servo/components/style/properties/longhand/svg.mako.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2820,34 +2820,18 @@ fn static_assert() {
     }
 
     ${impl_simple_copy("touch_action", "mTouchAction")}
 </%self:impl_trait>
 
 <%def name="simple_image_array_property(name, shorthand, field_name)">
     <%
         image_layers_field = "mImage" if shorthand == "background" else "mMask"
+        copy_simple_image_array_property(name, shorthand, image_layers_field, field_name)
     %>
-    pub fn copy_${shorthand}_${name}_from(&mut self, other: &Self) {
-        use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
-
-        let count = other.gecko.${image_layers_field}.${field_name}Count;
-        unsafe {
-            Gecko_EnsureImageLayersLength(&mut self.gecko.${image_layers_field},
-                                          count as usize,
-                                          LayerType::${shorthand.title()});
-        }
-        for (layer, other) in self.gecko.${image_layers_field}.mLayers.iter_mut()
-                                  .zip(other.gecko.${image_layers_field}.mLayers.iter())
-                                  .take(count as usize) {
-            layer.${field_name} = other.${field_name};
-        }
-        self.gecko.${image_layers_field}.${field_name}Count = count;
-    }
-
 
     pub fn set_${shorthand}_${name}<I>(&mut self, v: I)
         where I: IntoIterator<Item=longhands::${shorthand}_${name}::computed_value::single_value::T>,
               I::IntoIter: ExactSizeIterator
     {
         use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
         let v = v.into_iter();
 
@@ -2859,19 +2843,112 @@ fn static_assert() {
         self.gecko.${image_layers_field}.${field_name}Count = v.len() as u32;
         for (servo, geckolayer) in v.zip(self.gecko.${image_layers_field}.mLayers.iter_mut()) {
             geckolayer.${field_name} = {
                 ${caller.body()}
             };
         }
     }
 </%def>
+
+<%def name="copy_simple_image_array_property(name, shorthand, layers_field_name, field_name)">
+    pub fn copy_${shorthand}_${name}_from(&mut self, other: &Self) {
+        use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
+
+        let count = other.gecko.${layers_field_name}.${field_name}Count;
+        unsafe {
+            Gecko_EnsureImageLayersLength(&mut self.gecko.${layers_field_name},
+                                          count as usize,
+                                          LayerType::${shorthand.title()});
+        }
+        for (layer, other) in self.gecko.${layers_field_name}.mLayers.iter_mut()
+                                  .zip(other.gecko.${layers_field_name}.mLayers.iter())
+                                  .take(count as usize) {
+            layer.${field_name} = other.${field_name};
+        }
+        self.gecko.${layers_field_name}.${field_name}Count = count;
+    }
+</%def>
+
+<%def name="impl_simple_image_array_property(name, shorthand, layer_field_name, field_name, struct_name)">
+    <%
+        ident = "%s_%s" % (shorthand, name)
+        style_struct = next(x for x in data.style_structs if x.name == struct_name)
+        longhand = next(x for x in style_struct.longhands if x.ident == ident)
+        keyword = longhand.keyword
+    %>
+
+    <% copy_simple_image_array_property(name, shorthand, layer_field_name, field_name) %>
+
+    pub fn set_${ident}<I>(&mut self, v: I)
+        where I: IntoIterator<Item=longhands::${ident}::computed_value::single_value::T>,
+              I::IntoIter: ExactSizeIterator
+    {
+        use properties::longhands::${ident}::single_value::computed_value::T as Keyword;
+        use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
+
+        let v = v.into_iter();
+
+        unsafe {
+          Gecko_EnsureImageLayersLength(&mut self.gecko.${layer_field_name}, v.len(),
+                                        LayerType::${shorthand.title()});
+        }
+
+        self.gecko.${layer_field_name}.${field_name}Count = v.len() as u32;
+        for (servo, geckolayer) in v.zip(self.gecko.${layer_field_name}.mLayers.iter_mut()) {
+            geckolayer.${field_name} = {
+                match servo {
+                    % for value in keyword.values_for("gecko"):
+                    Keyword::${to_rust_ident(value)} =>
+                        structs::${keyword.gecko_constant(value)} ${keyword.maybe_cast('u8')},
+                    % endfor
+                }
+            };
+        }
+    }
+
+    pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T
+    {
+        use properties::longhands::${ident}::single_value::computed_value::T as Keyword;
+
+        % if keyword.needs_cast():
+        % for value in keyword.values_for('gecko'):
+        const ${keyword.casted_constant_name(value, "u8")} : u8 =
+            structs::${keyword.gecko_constant(value)} as u8;
+        % endfor
+        % endif
+
+        longhands::${ident}::computed_value::T (
+            self.gecko.${layer_field_name}.mLayers.iter()
+                .take(self.gecko.${layer_field_name}.${field_name}Count as usize)
+                .map(|ref layer| {
+                    match layer.${field_name} {
+                        % for value in longhand.keyword.values_for("gecko"):
+                        % if keyword.needs_cast():
+                        ${keyword.casted_constant_name(value, "u8")}
+                        % else:
+                        structs::${keyword.gecko_constant(value)}
+                        % endif
+                            => Keyword::${to_rust_ident(value)},
+                        % endfor
+                        x => panic!("Found unexpected value in style struct for ${ident} property: {:?}", x),
+                    }
+                }).collect()
+        )
+    }
+</%def>
+
 <%def name="impl_common_image_layer_properties(shorthand)">
     <%
-        image_layers_field = "mImage" if shorthand == "background" else "mMask"
+        if shorthand == "background":
+            image_layers_field = "mImage"
+            struct_name = "Background"
+        else:
+            image_layers_field = "mMask"
+            struct_name = "SVG"
     %>
 
     <%self:simple_image_array_property name="repeat" shorthand="${shorthand}" field_name="mRepeat">
         use properties::longhands::${shorthand}_repeat::single_value::computed_value::RepeatKeyword;
         use gecko_bindings::structs::nsStyleImageLayers_Repeat;
         use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
         use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_NO_REPEAT;
         use gecko_bindings::structs::NS_STYLE_IMAGELAYER_REPEAT_SPACE;
@@ -2889,50 +2966,18 @@ fn static_assert() {
         let repeat_x = to_ns(servo.0);
         let repeat_y = to_ns(servo.1);
         nsStyleImageLayers_Repeat {
               mXRepeat: repeat_x as u8,
               mYRepeat: repeat_y as u8,
         }
     </%self:simple_image_array_property>
 
-    <%self:simple_image_array_property name="clip" shorthand="${shorthand}" field_name="mClip">
-        use gecko_bindings::structs::StyleGeometryBox;
-        use properties::longhands::${shorthand}_clip::single_value::computed_value::T;
-
-        match servo {
-            T::border_box => StyleGeometryBox::BorderBox,
-            T::padding_box => StyleGeometryBox::PaddingBox,
-            T::content_box => StyleGeometryBox::ContentBox,
-            % if shorthand == "mask":
-            T::fill_box => StyleGeometryBox::FillBox,
-            T::stroke_box => StyleGeometryBox::StrokeBox,
-            T::view_box => StyleGeometryBox::ViewBox,
-            T::no_clip => StyleGeometryBox::NoClip,
-            % elif shorthand == "background":
-            T::text => StyleGeometryBox::Text,
-            % endif
-        }
-    </%self:simple_image_array_property>
-
-    <%self:simple_image_array_property name="origin" shorthand="${shorthand}" field_name="mOrigin">
-        use gecko_bindings::structs::StyleGeometryBox;
-        use properties::longhands::${shorthand}_origin::single_value::computed_value::T;
-
-        match servo {
-            T::border_box => StyleGeometryBox::BorderBox,
-            T::padding_box => StyleGeometryBox::PaddingBox,
-            T::content_box => StyleGeometryBox::ContentBox,
-            % if shorthand == "mask":
-            T::fill_box => StyleGeometryBox::FillBox,
-            T::stroke_box => StyleGeometryBox::StrokeBox,
-            T::view_box => StyleGeometryBox::ViewBox,
-            % endif
-        }
-    </%self:simple_image_array_property>
+    <% impl_simple_image_array_property("clip", shorthand, image_layers_field, "mClip", struct_name) %>
+    <% impl_simple_image_array_property("origin", shorthand, image_layers_field, "mOrigin", struct_name) %>
 
     % for orientation in ["x", "y"]:
     pub fn copy_${shorthand}_position_${orientation}_from(&mut self, other: &Self) {
         use gecko_bindings::structs::nsStyleImageLayers_LayerType as LayerType;
 
         let count = other.gecko.${image_layers_field}.mPosition${orientation.upper()}Count;
 
         unsafe {
@@ -3143,48 +3188,18 @@ fn static_assert() {
                                   background-blend-mode
                                   background-position-x
                                   background-position-y""" %>
 <%self:impl_trait style_struct_name="Background"
                   skip_longhands="${skip_background_longhands}"
                   skip_additionals="*">
 
     <% impl_common_image_layer_properties("background") %>
-
-    <%self:simple_image_array_property name="attachment" shorthand="background" field_name="mAttachment">
-        use properties::longhands::background_attachment::single_value::computed_value::T;
-        match servo {
-            T::scroll => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL as u8,
-            T::fixed => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED as u8,
-            T::local => structs::NS_STYLE_IMAGELAYER_ATTACHMENT_LOCAL as u8,
-        }
-    </%self:simple_image_array_property>
-
-    <%self:simple_image_array_property name="blend_mode" shorthand="background" field_name="mBlendMode">
-        use properties::longhands::background_blend_mode::single_value::computed_value::T;
-
-        match servo {
-            T::normal => structs::NS_STYLE_BLEND_NORMAL as u8,
-            T::multiply => structs::NS_STYLE_BLEND_MULTIPLY as u8,
-            T::screen => structs::NS_STYLE_BLEND_SCREEN as u8,
-            T::overlay => structs::NS_STYLE_BLEND_OVERLAY as u8,
-            T::darken => structs::NS_STYLE_BLEND_DARKEN as u8,
-            T::lighten => structs::NS_STYLE_BLEND_LIGHTEN as u8,
-            T::color_dodge => structs::NS_STYLE_BLEND_COLOR_DODGE as u8,
-            T::color_burn => structs::NS_STYLE_BLEND_COLOR_BURN as u8,
-            T::hard_light => structs::NS_STYLE_BLEND_HARD_LIGHT as u8,
-            T::soft_light => structs::NS_STYLE_BLEND_SOFT_LIGHT as u8,
-            T::difference => structs::NS_STYLE_BLEND_DIFFERENCE as u8,
-            T::exclusion => structs::NS_STYLE_BLEND_EXCLUSION as u8,
-            T::hue => structs::NS_STYLE_BLEND_HUE as u8,
-            T::saturation => structs::NS_STYLE_BLEND_SATURATION as u8,
-            T::color => structs::NS_STYLE_BLEND_COLOR as u8,
-            T::luminosity => structs::NS_STYLE_BLEND_LUMINOSITY as u8,
-        }
-    </%self:simple_image_array_property>
+    <% impl_simple_image_array_property("attachment", "background", "mImage", "mAttachment", "Background") %>
+    <% impl_simple_image_array_property("blend_mode", "background", "mImage", "mBlendMode", "Background") %>
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="List"
                   skip_longhands="list-style-image list-style-type quotes -moz-image-region"
                   skip_additionals="*">
 
     pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) {
         use values::Either;
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -344,17 +344,17 @@ impl AnimatedProperty {
     /// animation at `progress`.
     pub fn update(&self, style: &mut ComputedValues, progress: f64) {
         match *self {
             % for prop in data.longhands:
                 % if prop.animatable:
                     AnimatedProperty::${prop.camel_case}(ref from, ref to) => {
                         // https://w3c.github.io/web-animations/#discrete-animation-type
                         % if prop.animation_value_type == "discrete":
-                            let value = if progress < 0.5 { *from } else { *to };
+                            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
                         style.mutate_${prop.style_struct.ident.strip("_")}().set_${prop.ident}(value);
                     }
@@ -586,19 +586,19 @@ impl Animatable for AnimationValue {
         -> Result<Self, ()> {
         match (self, other) {
             % for prop in data.longhands:
                 % if prop.animatable:
                     (&AnimationValue::${prop.camel_case}(ref from),
                      &AnimationValue::${prop.camel_case}(ref to)) => {
                         % if prop.animation_value_type == "discrete":
                             if self_portion > other_portion {
-                                Ok(AnimationValue::${prop.camel_case}(*from))
+                                Ok(AnimationValue::${prop.camel_case}(from.clone()))
                             } else {
-                                Ok(AnimationValue::${prop.camel_case}(*to))
+                                Ok(AnimationValue::${prop.camel_case}(to.clone()))
                             }
                         % else:
                             from.add_weighted(to, self_portion, other_portion)
                                 .map(AnimationValue::${prop.camel_case})
                         % endif
                     }
                 % endif
             % endfor
--- a/servo/components/style/properties/longhand/background.mako.rs
+++ b/servo/components/style/properties/longhand/background.mako.rs
@@ -139,39 +139,43 @@
             }
         }
     }
 </%helpers:vector_longhand>
 
 ${helpers.single_keyword("background-attachment",
                          "scroll fixed" + (" local" if product == "gecko" else ""),
                          vector=True,
+                         gecko_constant_prefix="NS_STYLE_IMAGELAYER_ATTACHMENT",
                          spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment",
-                         animation_value_type="none")}
+                         animation_value_type="discrete")}
 
 ${helpers.single_keyword("background-clip",
                          "border-box padding-box content-box",
                          extra_gecko_values="text",
                          vector=True, extra_prefixes="webkit",
+                         gecko_enum_prefix="StyleGeometryBox",
                          spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip",
-                         animation_value_type="none")}
+                         animation_value_type="discrete")}
 
 ${helpers.single_keyword("background-origin",
                          "padding-box border-box content-box",
                          vector=True, extra_prefixes="webkit",
+                         gecko_enum_prefix="StyleGeometryBox",
                          spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin",
-                         animation_value_type="none")}
+                         animation_value_type="discrete")}
 
 ${helpers.predefined_type("background-size", "BackgroundSize",
     initial_value="computed::LengthOrPercentageOrAuto::Auto.into()",
     initial_specified_value="specified::LengthOrPercentageOrAuto::Auto.into()",
     spec="https://drafts.csswg.org/css-backgrounds/#the-background-size",
     vector=True,
     animation_value_type="ComputedValue",
     extra_prefixes="webkit")}
 
 // https://drafts.fxtf.org/compositing/#background-blend-mode
 ${helpers.single_keyword("background-blend-mode",
                          """normal multiply screen overlay darken lighten color-dodge
                             color-burn hard-light soft-light difference exclusion hue
                             saturation color luminosity""",
-                         vector=True, products="gecko", animation_value_type="none",
+                         gecko_constant_prefix="NS_STYLE_BLEND",
+                         vector=True, products="gecko", animation_value_type="discrete",
                          spec="https://drafts.fxtf.org/compositing/#background-blend-mode")}
--- a/servo/components/style/properties/longhand/svg.mako.rs
+++ b/servo/components/style/properties/longhand/svg.mako.rs
@@ -98,25 +98,27 @@
 % endfor
 
 ${helpers.single_keyword("mask-clip",
                          "border-box content-box padding-box",
                          extra_gecko_values="fill-box stroke-box view-box no-clip",
                          vector=True,
                          products="gecko",
                          extra_prefixes="webkit",
+                         gecko_enum_prefix="StyleGeometryBox",
                          animation_value_type="none",
                          spec="https://drafts.fxtf.org/css-masking/#propdef-mask-clip")}
 
 ${helpers.single_keyword("mask-origin",
                          "border-box content-box padding-box",
                          extra_gecko_values="fill-box stroke-box view-box",
                          vector=True,
                          products="gecko",
                          extra_prefixes="webkit",
+                         gecko_enum_prefix="StyleGeometryBox",
                          animation_value_type="none",
                          spec="https://drafts.fxtf.org/css-masking/#propdef-mask-origin")}
 
 <%helpers:longhand name="mask-size" products="gecko" animation_value_type="ComputedValue" extra_prefixes="webkit"
                    spec="https://drafts.fxtf.org/css-masking/#propdef-mask-size">
     use properties::longhands::background_size;
     pub use ::properties::longhands::background_size::SpecifiedValue;
     pub use ::properties::longhands::background_size::single_value as single_value;