Bug 1457635: Move represents_keyword to the css attributes. r?xidorn draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sun, 29 Apr 2018 04:48:47 +0200
changeset 789553 9bcabd5dea6ff19bd26cc3c969d192e1f204b360
parent 789552 98f7e1d5d51063e07e545f68425c9483d483ae50
child 789554 a49e0041d28054b131a2b76d4faa1e2c72c7eeed
push id108278
push userbmo:emilio@crisal.io
push dateSun, 29 Apr 2018 03:36:08 +0000
reviewersxidorn
bugs1457635
milestone61.0a1
Bug 1457635: Move represents_keyword to the css attributes. r?xidorn MozReview-Commit-ID: 21yuU4h34AQ
servo/components/style/values/generics/border.rs
servo/components/style/values/generics/effects.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/position.rs
servo/components/style_derive/specified_value_info.rs
servo/components/style_derive/to_css.rs
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -18,22 +18,23 @@ pub enum BorderImageSideWidth<LengthOrPe
     /// `<number>`
     Number(Number),
     /// `auto`
     Auto,
 }
 
 /// A generic value for the `border-image-slice` property.
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue)]
+         ToComputedValue, ToCss)]
 pub struct BorderImageSlice<NumberOrPercentage> {
     /// The offsets.
+    #[css(field_bound)]
     pub offsets: Rect<NumberOrPercentage>,
     /// Whether to fill the middle part.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub fill: bool,
 }
 
 /// A generic value for the `border-*-radius` longhand properties.
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf,
          PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
 pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size<L>);
 
@@ -81,32 +82,16 @@ where
     fn from(value: N) -> Self {
         Self {
             offsets: Rect::all(value),
             fill: false,
         }
     }
 }
 
-impl<N> ToCss for BorderImageSlice<N>
-where
-    N: PartialEq + ToCss,
-{
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        self.offsets.to_css(dest)?;
-        if self.fill {
-            dest.write_str(" fill")?;
-        }
-        Ok(())
-    }
-}
-
 impl<L> BorderRadius<L> {
     /// Returns a new `BorderRadius<L>`.
     #[inline]
     pub fn new(
         tl: BorderCornerRadius<L>,
         tr: BorderCornerRadius<L>,
         br: BorderCornerRadius<L>,
         bl: BorderCornerRadius<L>,
--- a/servo/components/style/values/generics/effects.rs
+++ b/servo/components/style/values/generics/effects.rs
@@ -1,30 +1,28 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 //! Generic types for CSS values related to effects.
 
-use std::fmt::{self, Write};
-use style_traits::values::{CssWriter, SequenceWriter, ToCss};
 #[cfg(feature = "gecko")]
 use values::specified::url::SpecifiedUrl;
 
 /// A generic value for a single `box-shadow`.
 #[derive(Animate, Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToAnimatedValue, ToAnimatedZero)]
+         ToAnimatedValue, ToAnimatedZero, ToCss)]
 pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
     /// The base shadow.
     pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
     /// The spread radius.
     pub spread: ShapeLength,
     /// Whether this is an inset box shadow.
     #[animation(constant)]
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub inset: bool,
 }
 
 /// A generic value for a single `filter`.
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 #[derive(Clone, ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,
          SpecifiedValueInfo, ToAnimatedValue, ToComputedValue, ToCss)]
 pub enum Filter<Angle, Factor, Length, DropShadow> {
@@ -75,32 +73,8 @@ pub struct SimpleShadow<Color, SizeLengt
     pub color: Color,
     /// Horizontal radius.
     pub horizontal: SizeLength,
     /// Vertical radius.
     pub vertical: SizeLength,
     /// Blur radius.
     pub blur: ShapeLength,
 }
-
-impl<Color, SizeLength, BlurShapeLength, ShapeLength> ToCss
-    for BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength>
-where
-    Color: ToCss,
-    SizeLength: ToCss,
-    BlurShapeLength: ToCss,
-    ShapeLength: ToCss,
-{
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        {
-            let mut writer = SequenceWriter::new(&mut *dest, " ");
-            writer.item(&self.base)?;
-            writer.item(&self.spread)?;
-        }
-        if self.inset {
-            dest.write_str(" inset")?;
-        }
-        Ok(())
-    }
-}
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -1942,21 +1942,21 @@ impl Parse for FontFeatureSettings {
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo,
          ToComputedValue)]
 /// Whether user agents are allowed to synthesize bold or oblique font faces
 /// when a font family lacks bold or italic faces
 pub struct FontSynthesis {
     /// If a `font-weight` is requested that the font family does not contain,
     /// the user agent may synthesize the requested weight from the weights
     /// that do exist in the font family.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub weight: bool,
     /// If a font-style is requested that the font family does not contain,
     /// the user agent may synthesize the requested style from the normal face in the font family.
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub style: bool,
 }
 
 impl FontSynthesis {
     #[inline]
     /// Get the default value of font-synthesis
     pub fn get_initial_value() -> Self {
         FontSynthesis {
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -419,52 +419,38 @@ pub enum AutoFlow {
     /// adding new rows as necessary.
     Row,
     /// The auto-placement algorithm places items by filling each column in turn,
     /// adding new columns as necessary.
     Column,
 }
 
 #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo,
-         ToComputedValue)]
+         ToComputedValue, ToCss)]
 /// Controls how the auto-placement algorithm works
 /// specifying exactly how auto-placed items get flowed into the grid
 pub struct GridAutoFlow {
     /// Specifiy how auto-placement algorithm fills each `row` or `column` in turn
     pub autoflow: AutoFlow,
     /// Specify use `dense` packing algorithm or not
-    #[value_info(represents_keyword)]
+    #[css(represents_keyword)]
     pub dense: bool,
 }
 
 impl GridAutoFlow {
     #[inline]
     /// Get default `grid-auto-flow` as `row`
     pub fn row() -> GridAutoFlow {
         GridAutoFlow {
             autoflow: AutoFlow::Row,
             dense: false,
         }
     }
 }
 
-impl ToCss for GridAutoFlow {
-    fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
-    where
-        W: Write,
-    {
-        self.autoflow.to_css(dest)?;
-
-        if self.dense {
-            dest.write_str(" dense")?;
-        }
-        Ok(())
-    }
-}
-
 impl Parse for GridAutoFlow {
     /// [ row | column ] || dense
     fn parse<'i, 't>(
         _context: &ParserContext,
         input: &mut Parser<'i, 't>,
     ) -> Result<GridAutoFlow, ParseError<'i>> {
         let mut value = None;
         let mut dense = false;
--- a/servo/components/style_derive/specified_value_info.rs
+++ b/servo/components/style_derive/specified_value_info.rs
@@ -135,23 +135,23 @@ fn derive_struct_fields<'a>(
     };
     types.extend(fields.filter_map(|field| {
         let info_attrs = cg::parse_field_attrs::<ValueInfoFieldAttrs>(field);
         if let Some(other_values) = info_attrs.other_values {
             for value in other_values.split(",") {
                 values.push(value.to_string());
             }
         }
-        if info_attrs.represents_keyword {
+        let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
+        if css_attrs.represents_keyword {
             let ident = field.ident.as_ref()
                 .expect("only named field should use represents_keyword");
             values.push(cg::to_css_identifier(ident.as_ref()));
             return None;
         }
-        let css_attrs = cg::parse_field_attrs::<CssFieldAttrs>(field);
         if let Some(if_empty) = css_attrs.if_empty {
             values.push(if_empty);
         }
         if !css_attrs.skip {
             Some(&field.ty)
         } else {
             None
         }
@@ -171,11 +171,10 @@ struct ValueInfoInputAttrs {
 struct ValueInfoVariantAttrs {
     starts_with_keyword: bool,
     other_values: Option<String>,
 }
 
 #[darling(attributes(value_info), default)]
 #[derive(Default, FromField)]
 struct ValueInfoFieldAttrs {
-    represents_keyword: bool,
     other_values: Option<String>,
 }
--- a/servo/components/style_derive/to_css.rs
+++ b/servo/components/style_derive/to_css.rs
@@ -184,21 +184,31 @@ fn derive_single_field_expr(
                 }
             };
         }
         quote! {
             for item in #field.iter() {
                 writer.item(&item)?;
             }
         }
+    } else if attrs.represents_keyword {
+        let ident =
+            field.ast().ident.as_ref().expect("Unnamed field with represents_keyword?");
+        let ident = cg::to_css_identifier(ident.as_ref());
+        quote! {
+            if *#field {
+                writer.raw_item(#ident)?;
+            }
+        }
     } else {
         if attrs.field_bound {
             let ty = &field.ast().ty;
             cg::add_predicate(where_clause, parse_quote!(#ty: ::style_traits::ToCss));
         }
+
         quote! { writer.item(#field)?; }
     };
 
     if let Some(condition) = attrs.skip_if {
         expr = quote! {
             if !#condition(#field) {
                 #expr
             }
@@ -231,10 +241,11 @@ pub struct CssVariantAttrs {
 
 #[darling(attributes(css), default)]
 #[derive(Default, FromField)]
 pub struct CssFieldAttrs {
     pub if_empty: Option<String>,
     pub field_bound: bool,
     pub iterable: bool,
     pub skip: bool,
+    pub represents_keyword: bool,
     pub skip_if: Option<Path>,
 }