servo: Merge #10957 - Support plain number-typed properties in geckolib (from heycam:number); r=bholley
authorCameron McCormack <cam@mcc.id.au>
Mon, 02 May 2016 21:58:17 -0700
changeset 338695 e0e4b673eeead8be1bf21263d3a1fea5030f808b
parent 338694 046ef257ead6c0681f647530e9ce05b381909ba3
child 338696 1d4a400f5cc6e896bba4ea51ba509df43a9aecf3
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
servo: Merge #10957 - Support plain number-typed properties in geckolib (from heycam:number); r=bholley r? @bholley Source-Repo: https://github.com/servo/servo Source-Revision: ddada69acb4dc64859c9b209a18546c7c082f314
servo/components/style/properties/data.py
servo/components/style/properties/helpers.mako.rs
servo/components/style/properties/longhand/effects.mako.rs
servo/components/style/properties/longhand/position.mako.rs
servo/components/style/properties/longhand/svg.mako.rs
servo/components/style/properties/longhand/svg_inherited.mako.rs
servo/components/style/properties/longhand/xul.mako.rs
servo/components/style/values.rs
servo/ports/geckolib/properties.mako.rs
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -41,20 +41,21 @@ class Keyword(object):
             raise Exception("Bad product: " + product)
 
     def gecko_constant(self, value):
         return self.gecko_constant_prefix + "_" + value.replace("-moz-", "").replace("-", "_").upper()
 
 
 class Longhand(object):
     def __init__(self, style_struct, name, derived_from=None, keyword=None,
-                 custom_cascade=False, experimental=False, internal=False,
+                 predefined_type=None, custom_cascade=False, experimental=False, internal=False,
                  need_clone=False, gecko_ffi_name=None):
         self.name = name
         self.keyword = keyword
+        self.predefined_type = predefined_type
         self.ident = to_rust_ident(name)
         self.camel_case = to_camel_case(self.ident)
         self.style_struct = style_struct
         self.experimental = ("layout.%s.enabled" % name) if experimental else None
         self.custom_cascade = custom_cascade
         self.internal = internal
         self.need_clone = need_clone
         self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case
--- a/servo/components/style/properties/helpers.mako.rs
+++ b/servo/components/style/properties/helpers.mako.rs
@@ -12,17 +12,17 @@
                                -> Result<DeclaredValue<SpecifiedValue>, ()> {
                 parse(context, input).map(DeclaredValue::Value)
             }
         % endif
     </%call>
 </%def>
 
 <%def name="predefined_type(name, type, initial_value, parse_method='parse', **kwargs)">
-    <%call expr="longhand(name, **kwargs)">
+    <%call expr="longhand(name, predefined_type=type, **kwargs)">
         #[allow(unused_imports)]
         use app_units::Au;
         pub type SpecifiedValue = specified::${type};
         pub mod computed_value {
             pub use values::computed::${type} as T;
         }
         #[inline] pub fn get_initial_value() -> computed_value::T { ${initial_value} }
         #[inline] pub fn parse(_context: &ParserContext, input: &mut Parser)
--- a/servo/components/style/properties/longhand/effects.mako.rs
+++ b/servo/components/style/properties/longhand/effects.mako.rs
@@ -2,56 +2,19 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 // Box-shadow, etc.
 <% data.new_style_struct("Effects", inherited=False) %>
 
-<%helpers:longhand name="opacity">
-    use cssparser::ToCss;
-    use std::fmt;
-    use values::CSSFloat;
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            self.0.to_css(dest)
-        }
-    }
-
-    #[derive(Debug, Clone, PartialEq, HeapSizeOf)]
-    pub struct SpecifiedValue(pub CSSFloat);
-    pub mod computed_value {
-        use values::CSSFloat;
-        pub type T = CSSFloat;
-    }
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        1.0
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value<Cx: TContext>(&self, _context: &Cx) -> computed_value::T {
-            if self.0 < 0.0 {
-                0.0
-            } else if self.0 > 1.0 {
-                1.0
-            } else {
-                self.0
-            }
-        }
-    }
-    fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
-        specified::parse_number(input).map(SpecifiedValue)
-    }
-</%helpers:longhand>
+${helpers.predefined_type("opacity",
+                          "Opacity",
+                          "1.0")}
 
 <%helpers:longhand name="box-shadow">
     use cssparser::{self, ToCss};
     use std::fmt;
     use values::AuExtensionMethods;
 
     #[derive(Debug, Clone, PartialEq, HeapSizeOf)]
     pub struct SpecifiedValue(Vec<SpecifiedBoxShadow>);
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -58,16 +58,21 @@
 </%helpers:longhand>
 
 // CSS Flexible Box Layout Module Level 1
 // http://www.w3.org/TR/css3-flexbox/
 
 // Flex container properties
 ${helpers.single_keyword("flex-direction", "row row-reverse column column-reverse", experimental=True)}
 
+// Flex item properties
+${helpers.predefined_type("flex-grow", "Number", "0.0", "parse_non_negative", products="gecko")}
+
+${helpers.predefined_type("flex-shrink", "Number", "1.0", "parse_non_negative", products="gecko")}
+
 // https://drafts.csswg.org/css-flexbox/#propdef-order
 <%helpers:longhand name="order">
     use values::computed::ComputedValueAsSpecified;
 
     impl ComputedValueAsSpecified for SpecifiedValue {}
 
     pub type SpecifiedValue = computed_value::T;
 
--- a/servo/components/style/properties/longhand/svg.mako.rs
+++ b/servo/components/style/properties/longhand/svg.mako.rs
@@ -8,11 +8,19 @@
 
 ${helpers.single_keyword("dominant-baseline",
                  """auto use-script no-change reset-size ideographic alphabetic hanging
                     mathematical central middle text-after-edge text-before-edge""",
                  products="gecko")}
 
 ${helpers.single_keyword("vector-effect", "none non-scaling-stroke", products="gecko")}
 
+// Section 13 - Gradients and Patterns
+
+${helpers.predefined_type("stop-opacity", "Opacity", "1.0", products="gecko")}
+
+// Section 15 - Filter Effects
+
+${helpers.predefined_type("flood-opacity", "Opacity", "1.0", products="gecko")}
+
 // CSS Masking Module Level 1
 // https://www.w3.org/TR/css-masking-1/
 ${helpers.single_keyword("mask-type", "luminance alpha", products="gecko")}
--- a/servo/components/style/properties/longhand/svg_inherited.mako.rs
+++ b/servo/components/style/properties/longhand/svg_inherited.mako.rs
@@ -17,22 +17,29 @@
 // Section 11 - Painting: Filling, Stroking and Marker Symbols
 ${helpers.single_keyword("color-interpolation", "auto sRGB linearRGB", products="gecko")}
 
 ${helpers.single_keyword("color-interpolation-filters",
                          "auto sRGB linearRGB",
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION")}
 
+${helpers.predefined_type("fill-opacity", "Opacity", "1.0", products="gecko")}
+
 ${helpers.single_keyword("fill-rule", "nonzero evenodd", products="gecko")}
 
 ${helpers.single_keyword("shape-rendering",
                          "auto optimizeSpeed crispEdges geometricPrecision",
                          products="gecko")}
 
 ${helpers.single_keyword("stroke-linecap", "butt round square", products="gecko")}
 
 ${helpers.single_keyword("stroke-linejoin", "miter round bevel", products="gecko")}
 
+${helpers.predefined_type("stroke-miterlimit", "Number", "4.0", "parse_at_least_one",
+                          products="gecko")}
+
+${helpers.predefined_type("stroke-opacity", "Opacity", "1.0", products="gecko")}
+
 // Section 14 - Clipping, Masking and Compositing
 ${helpers.single_keyword("clip-rule", "nonzero evenodd",
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_FILL_RULE")}
--- a/servo/components/style/properties/longhand/xul.mako.rs
+++ b/servo/components/style/properties/longhand/xul.mako.rs
@@ -5,8 +5,11 @@
 <%namespace name="helpers" file="/helpers.mako.rs" />
 <% from data import Method %>
 
 // Non-standard properties that Gecko uses for XUL elements.
 <% data.new_style_struct("XUL", inherited=False) %>
 
 ${helpers.single_keyword("-moz-box-align", "stretch start center baseline end", products="gecko",
                          gecko_ffi_name="mBoxAlign", gecko_constant_prefix="NS_STYLE_BOX_ALIGN")}
+
+${helpers.predefined_type("-moz-box-flex", "Number", "0.0", "parse_non_negative", products="gecko",
+                          gecko_ffi_name="mBoxFlex")}
--- a/servo/components/style/values.rs
+++ b/servo/components/style/values.rs
@@ -1470,16 +1470,83 @@ pub mod specified {
         }
     }
 
     impl ToCss for Time {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             write!(dest, "{}s", self.0)
         }
     }
+
+    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, HeapSizeOf)]
+    pub struct Number(pub CSSFloat);
+
+    impl Number {
+        pub fn parse(input: &mut Parser) -> Result<Number, ()> {
+            parse_number(input).map(Number)
+        }
+
+        fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> {
+            match parse_number(input) {
+                Ok(value) if value < min => Err(()),
+                value => value.map(Number),
+            }
+        }
+
+        pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
+            Number::parse_with_minimum(input, 0.0)
+        }
+
+        pub fn parse_at_least_one(input: &mut Parser) -> Result<Number, ()> {
+            Number::parse_with_minimum(input, 1.0)
+        }
+    }
+
+    impl ToComputedValue for Number {
+        type ComputedValue = CSSFloat;
+
+        #[inline]
+        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> CSSFloat { self.0 }
+    }
+
+    impl ToCss for Number {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            self.0.to_css(dest)
+        }
+    }
+
+    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, HeapSizeOf)]
+    pub struct Opacity(pub CSSFloat);
+
+    impl Opacity {
+        pub fn parse(input: &mut Parser) -> Result<Opacity, ()> {
+            parse_number(input).map(Opacity)
+        }
+    }
+
+    impl ToComputedValue for Opacity {
+        type ComputedValue = CSSFloat;
+
+        #[inline]
+        fn to_computed_value<Cx: TContext>(&self, _: &Cx) -> CSSFloat {
+            if self.0 < 0.0 {
+                0.0
+            } else if self.0 > 1.0 {
+                1.0
+            } else {
+                self.0
+            }
+        }
+    }
+
+    impl ToCss for Opacity {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+            self.0.to_css(dest)
+        }
+    }
 }
 
 pub mod computed {
     use app_units::Au;
     use euclid::size::Size2D;
     use properties::ComputedValues;
     use properties::style_struct_traits::Font;
     use std::fmt;
@@ -2082,9 +2149,11 @@ pub mod computed {
                             Some(value) => Some(value.to_computed_value(context)),
                         },
                     }
                 }).collect()
             }
         }
     }
     pub type Length = Au;
+    pub type Number = CSSFloat;
+    pub type Opacity = CSSFloat;
 }
--- a/servo/ports/geckolib/properties.mako.rs
+++ b/servo/ports/geckolib/properties.mako.rs
@@ -123,16 +123,22 @@ impl ComputedValues for GeckoComputedVal
 
 <%def name="declare_style_struct(style_struct)">
 #[derive(Clone, HeapSizeOf, Debug)]
 pub struct ${style_struct.gecko_struct_name} {
     gecko: ${style_struct.gecko_ffi_name},
 }
 </%def>
 
+<%def name="impl_simple_setter(ident, gecko_ffi_name)">
+    fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
+        ${set_gecko_property(gecko_ffi_name, "v")}
+    }
+</%def>
+
 <%def name="impl_simple_copy(ident, gecko_ffi_name)">
     fn copy_${ident}_from(&mut self, other: &Self) {
         self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
     }
 </%def>
 
 <%!
 def is_border_style_masked(ffi_name):
@@ -181,16 +187,21 @@ def set_gecko_property(ffi_name, expr):
 <%def name="impl_keyword(ident, gecko_ffi_name, keyword, need_clone)">
 <%call expr="impl_keyword_setter(ident, gecko_ffi_name, keyword)"></%call>
 <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
 %if need_clone:
 <%call expr="impl_keyword_clone(ident, gecko_ffi_name, keyword)"></%call>
 % endif
 </%def>
 
+<%def name="impl_simple(ident, gecko_ffi_name)">
+<%call expr="impl_simple_setter(ident, gecko_ffi_name)"></%call>
+<%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
+</%def>
+
 <%def name="impl_app_units(ident, gecko_ffi_name, need_clone)">
     fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         self.gecko.${gecko_ffi_name} = v.0;
     }
 <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
 %if need_clone:
     fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
         Au(self.gecko.${gecko_ffi_name})
@@ -279,31 +290,40 @@ impl Debug for ${style_struct.gecko_ffi_
    force_stub += ["list-style-type", "text-overflow"]
    # Enum class instead of NS_STYLE_...
    force_stub += ["box-sizing"]
    # Inconsistent constant naming in gecko
    force_stub += ["text-transform"]
    # These are booleans.
    force_stub += ["page-break-after", "page-break-before"]
 
+   simple_types = ["Number", "Opacity"]
+
    keyword_longhands = [x for x in longhands if x.keyword and not x.name in force_stub]
-   stub_longhands = [x for x in longhands if x not in keyword_longhands]
+   simple_longhands = [x for x in longhands
+                       if x.predefined_type in simple_types and not x.name in force_stub]
+
+   autogenerated_longhands = keyword_longhands + simple_longhands
+   stub_longhands = [x for x in longhands if x not in autogenerated_longhands]
 %>
 impl ${style_struct.trait_name} for ${style_struct.gecko_struct_name} {
     /*
      * Manually-Implemented Methods.
      */
     ${caller.body().strip()}
 
     /*
      * Auto-Generated Methods.
      */
     % for longhand in keyword_longhands:
     <%call expr="impl_keyword(longhand.ident, longhand.gecko_ffi_name, longhand.keyword, longhand.need_clone)"></%call>
     % endfor
+    % for longhand in simple_longhands:
+    <%call expr="impl_simple(longhand.ident, longhand.gecko_ffi_name)"></%call>
+    % endfor
 
     /*
      * Stubs.
      */
     % for longhand in stub_longhands:
     fn set_${longhand.ident}(&mut self, _: longhands::${longhand.ident}::computed_value::T) {
         println!("stylo: Unimplemented property setter: ${longhand.name}");
     }