Bug 1354876 - Implement font-variant shorthand. r?heycam draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Thu, 13 Apr 2017 16:04:20 +0900
changeset 561786 6b4d814d8b1db7883b6be8e047c0e045a2a11a66
parent 561770 4bc4c40d4d05e5f5c1534f1306307d88f0c71f66
child 561787 7c85c68a2ca28016d4ad0b2cd32261e1a3530321
push id53868
push userhikezoe@mozilla.com
push dateThu, 13 Apr 2017 07:04:47 +0000
reviewersheycam
bugs1354876
milestone55.0a1
Bug 1354876 - Implement font-variant shorthand. r?heycam MozReview-Commit-ID: 4A01LwIDNfS
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/shorthand/font.mako.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -645,18 +645,16 @@ impl Debug for ${style_struct.gecko_stru
 <%
     longhands = [x for x in style_struct.longhands
                 if not (skip_longhands == "*" or x.name in skip_longhands.split())]
 
     #
     # Make a list of types we can't auto-generate.
     #
     force_stub = [];
-    # These live in an nsFont member in Gecko. Should be straightforward to do manually.
-    force_stub += ["font-variant"]
     # These have unusual representations in gecko.
     force_stub += ["list-style-type"]
 
     # Types used with predefined_type()-defined properties that we can auto-generate.
     predefined_types = {
         "length::LengthOrAuto": impl_style_coord,
         "length::LengthOrNormal": impl_style_coord,
         "Length": impl_absolute_length,
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -222,33 +222,28 @@
 
 ${helpers.single_keyword("font-style",
                          "normal italic oblique",
                          gecko_constant_prefix="NS_FONT_STYLE",
                          gecko_ffi_name="mFont.style",
                          spec="https://drafts.csswg.org/css-fonts/#propdef-font-style",
                          animation_type="none")}
 
-${helpers.single_keyword("font-variant",
-                         "normal small-caps",
-                         spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant",
-                         animation_type="none")}
-
 
 <% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
                                       "all-small": "ALLSMALL",
                                       "petite-caps": "PETITECAPS",
                                       "all-petite": "ALLPETITE",
                                       "titling-caps": "TITLING" } %>
 
 ${helpers.single_keyword("font-variant-caps",
-                         "normal small-caps all-small petite-caps unicase titling-caps",
+                         "normal small-caps",
+                         extra_gecko_values="all-small petite-caps unicase titling-caps",
                          gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
                          gecko_ffi_name="mFont.variantCaps",
-                         products="gecko",
                          spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
                          custom_consts=font_variant_caps_custom_consts,
                          animation_type="none")}
 
 <%helpers:longhand name="font-weight" need_clone="True" animation_type="normal"
                    spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight">
     use std::fmt;
     use style_traits::ToCss;
--- a/servo/components/style/properties/shorthand/font.mako.rs
+++ b/servo/components/style/properties/shorthand/font.mako.rs
@@ -1,35 +1,45 @@
 /* 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/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <%helpers:shorthand name="font"
-                    sub_properties="font-style font-variant font-weight font-stretch
+                    sub_properties="font-style font-variant-caps font-weight font-stretch
                                     font-size line-height font-family
                                     ${'font-size-adjust' if product == 'gecko' or data.testing else ''}
                                     ${'font-kerning' if product == 'gecko' or data.testing else ''}
-                                    ${'font-variant-caps' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-alternates' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-east-asian' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-ligatures' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-numeric' if product == 'gecko' or data.testing else ''}
                                     ${'font-variant-position' if product == 'gecko' or data.testing else ''}
                                     ${'font-language-override' if product == 'gecko' or data.testing else ''}"
                     spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
-    use properties::longhands::{font_style, font_variant, font_weight, font_stretch};
+    use properties::longhands::{font_style, font_variant_caps, font_weight, font_stretch};
     use properties::longhands::{font_size, line_height};
+    <%
+        gecko_sub_properties = "kerning language_override size_adjust \
+                                variant_alternates variant_east_asian \
+                                variant_ligatures variant_numeric \
+                                variant_position".split()
+    %>
     % if product == "gecko" or data.testing:
-    use properties::longhands::{font_size_adjust, font_kerning, font_variant_caps, font_variant_position,
-                                font_language_override};
+        % for prop in gecko_sub_properties:
+            use properties::longhands::font_${prop};
+        % endfor
     % endif
     use properties::longhands::font_family::SpecifiedValue as FontFamily;
 
     pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
         let mut nb_normals = 0;
         let mut style = None;
-        let mut variant = None;
+        let mut variant_caps = None;
         let mut weight = None;
         let mut stretch = None;
         let size;
         loop {
             // Special-case 'normal' because it is valid in each of
             // font-style, font-weight, font-variant and font-stretch.
             // Leaves the values to None, 'normal' is the initial value for each of them.
             if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
@@ -43,71 +53,72 @@
                 }
             }
             if weight.is_none() {
                 if let Ok(value) = input.try(|input| font_weight::parse(context, input)) {
                     weight = Some(value);
                     continue
                 }
             }
-            if variant.is_none() {
-                if let Ok(value) = input.try(|input| font_variant::parse(context, input)) {
-                    variant = Some(value);
+            if variant_caps.is_none() {
+                if let Ok(value) = input.try(|input| font_variant_caps::parse(context, input)) {
+                    variant_caps = Some(value);
                     continue
                 }
             }
             if stretch.is_none() {
                 if let Ok(value) = input.try(|input| font_stretch::parse(context, input)) {
                     stretch = Some(value);
                     continue
                 }
             }
             size = Some(try!(font_size::parse(context, input)));
             break
         }
         #[inline]
         fn count<T>(opt: &Option<T>) -> u8 {
             if opt.is_some() { 1 } else { 0 }
         }
-        if size.is_none() || (count(&style) + count(&weight) + count(&variant) + count(&stretch) + nb_normals) > 4 {
+        if size.is_none() ||
+           (count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
             return Err(())
         }
         let line_height = if input.try(|input| input.expect_delim('/')).is_ok() {
             Some(try!(line_height::parse(context, input)))
         } else {
             None
         };
         let family = FontFamily::parse(input)?;
         Ok(Longhands {
-            % for name in "style variant weight stretch size".split():
+            % for name in "style variant_caps weight stretch size".split():
                 font_${name}: unwrap_or_initial!(font_${name}, ${name}),
             % endfor
             line_height: unwrap_or_initial!(line_height),
             font_family: family,
             % if product == "gecko" or data.testing:
-                % for name in "size_adjust kerning variant_caps variant_position language_override".split():
+                % for name in gecko_sub_properties:
                     font_${name}: font_${name}::get_initial_specified_value(),
                 % endfor
             % endif
         })
     }
 
     // This may be a bit off, unsure, possibly needs changes
     impl<'a> ToCss for LonghandsToSerialize<'a>  {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
 
     % if product == "gecko" or data.testing:
-        % for name in "size_adjust kerning variant_caps variant_position language_override".split():
+        % for name in gecko_sub_properties:
             if self.font_${name} != &font_${name}::get_initial_specified_value() {
                 return Ok(());
             }
         % endfor
     % endif
 
-    % for name in "style variant weight stretch".split():
+    % for name in "style variant_caps weight stretch".split():
             self.font_${name}.to_css(dest)?;
             dest.write_str(" ")?;
     % endfor
 
             self.font_size.to_css(dest)?;
 
             match *self.line_height {
                 line_height::SpecifiedValue::Normal => {},
@@ -119,8 +130,81 @@
 
             dest.write_str(" ")?;
             self.font_family.to_css(dest)?;
 
             Ok(())
         }
     }
 </%helpers:shorthand>
+
+<%helpers:shorthand name="font-variant"
+                    sub_properties="font-variant-caps
+                                    ${'font-variant-alternates' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-east-asian' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-ligatures' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-numeric' if product == 'gecko' or data.testing else ''}
+                                    ${'font-variant-position' if product == 'gecko' or data.testing else ''}"
+                    spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-variant">
+    use properties::longhands::font_variant_caps;
+    <% gecko_sub_properties = "alternates east_asian ligatures numeric position".split() %>
+    % if product == "gecko" or data.testing:
+        % for prop in gecko_sub_properties:
+            use properties::longhands::font_variant_${prop};
+        % endfor
+    % endif
+
+    pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
+        let mut nb_normals = 0;
+        let mut caps = None;
+        loop {
+            // Special-case 'normal' because it is valid in each of
+            // all sub properties.
+            // Leaves the values to None, 'normal' is the initial value for each of them.
+            if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
+                nb_normals += 1;
+                continue;
+            }
+            if caps.is_none() {
+                if let Ok(value) = input.try(|input| font_variant_caps::parse(context, input)) {
+                    caps = Some(value);
+                    continue
+                }
+            }
+            break
+        }
+        #[inline]
+        fn count<T>(opt: &Option<T>) -> u8 {
+            if opt.is_some() { 1 } else { 0 }
+        }
+        let count = count(&caps) + nb_normals;
+        if count == 0 || count > 1 {
+            return Err(())
+        }
+        Ok(Longhands {
+            font_variant_caps: unwrap_or_initial!(font_variant_caps, caps),
+            // FIXME: Bug 1356134 - parse all sub properties.
+            % if product == "gecko" or data.testing:
+                % for name in gecko_sub_properties:
+                    font_variant_${name}: font_variant_${name}::get_initial_specified_value(),
+                % endfor
+            % endif
+        })
+    }
+
+    impl<'a> ToCss for LonghandsToSerialize<'a>  {
+        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+
+    % if product == "gecko" or data.testing:
+        % for name in gecko_sub_properties:
+            // FIXME: Bug 1356134 - handle all sub properties.
+            if self.font_variant_${name} != &font_variant_${name}::get_initial_specified_value() {
+                return Ok(());
+            }
+        % endfor
+    % endif
+
+            self.font_variant_caps.to_css(dest)?;
+
+            Ok(())
+        }
+    }
+</%helpers:shorthand>