servo: Merge #19188 - style: Move font-language-override outside of mako (from CYBAI:font-language-override-out-of-mako); r=emilio
authorCYBAI <cyb.ai.815@gmail.com>
Mon, 13 Nov 2017 10:20:22 -0600
changeset 391588 f062dbcb3bc106331eb8146a02f3b129c4cb4b3e
parent 391587 d720dddd8e4e22f6470efb35f0b795e3dd899376
child 391589 97b74ed9cfddf352e007f695e1712a3a4835c746
push id97297
push userncsoregi@mozilla.com
push dateMon, 13 Nov 2017 23:01:19 +0000
treeherdermozilla-inbound@1f7a23820597 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
servo: Merge #19188 - style: Move font-language-override outside of mako (from CYBAI:font-language-override-out-of-mako); r=emilio This is a sub-PR of #19015 r? emilio --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #19187 - [x] These changes do not require tests Source-Repo: https://github.com/servo/servo Source-Revision: c261ff38c76c584fc93a4cded2ffe0d724d318fd
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/mod.rs
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -1219,172 +1219,25 @@ https://drafts.csswg.org/css-fonts-4/#lo
 
     /// normal | <feature-tag-value>#
     pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         computed_value::T::parse(context, input)
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="font-language-override" products="gecko" animation_value_type="discrete"
-                   extra_prefixes="moz" boxed="True"
-                   flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
-                   spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
-    use properties::longhands::system_font::SystemFont;
-    use std::fmt;
-    use style_traits::ToCss;
-    use byteorder::{BigEndian, ByteOrder};
-
-    #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
-    pub enum SpecifiedValue {
-        Normal,
-        Override(String),
-        System(SystemFont)
-    }
-
-    impl ToCss for SpecifiedValue {
-        fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-            match *self {
-                SpecifiedValue::Normal => dest.write_str("normal"),
-                SpecifiedValue::Override(ref lang) => lang.to_css(dest),
-                SpecifiedValue::System(sys) => sys.to_css(dest),
-            }
-        }
-    }
-
-    impl SpecifiedValue {
-        pub fn system_font(f: SystemFont) -> Self {
-            SpecifiedValue::System(f)
-        }
-        pub fn get_system(&self) -> Option<SystemFont> {
-            if let SpecifiedValue::System(s) = *self {
-                Some(s)
-            } else {
-                None
-            }
-        }
-    }
-
-    pub mod computed_value {
-        use std::{fmt, str};
-        use style_traits::ToCss;
-        use byteorder::{BigEndian, ByteOrder};
-
-        impl ToCss for T {
-            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
-                if self.0 == 0 {
-                    return dest.write_str("normal")
-                }
-                let mut buf = [0; 4];
-                BigEndian::write_u32(&mut buf, self.0);
-                // Safe because we ensure it's ASCII during computing
-                let slice = if cfg!(debug_assertions) {
-                    str::from_utf8(&buf).unwrap()
-                } else {
-                    unsafe { str::from_utf8_unchecked(&buf) }
-                };
-                slice.trim_right().to_css(dest)
-            }
-        }
-
-        // font-language-override can only have a single three-letter
-        // OpenType "language system" tag, so we should be able to compute
-        // it and store it as a 32-bit integer
-        // (see http://www.microsoft.com/typography/otspec/languagetags.htm).
-        #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
-        pub struct T(pub u32);
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T(0)
-    }
-
-    #[inline]
-    pub fn get_initial_specified_value() -> SpecifiedValue {
-        SpecifiedValue::Normal
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value(&self, _context: &Context) -> computed_value::T {
-            #[allow(unused_imports)] use std::ascii::AsciiExt;
-            match *self {
-                SpecifiedValue::Normal => computed_value::T(0),
-                SpecifiedValue::Override(ref lang) => {
-                    if lang.is_empty() || lang.len() > 4 || !lang.is_ascii() {
-                        return computed_value::T(0)
-                    }
-                    let mut computed_lang = lang.clone();
-                    while computed_lang.len() < 4 {
-                        computed_lang.push(' ');
-                    }
-                    let bytes = computed_lang.into_bytes();
-                    computed_value::T(BigEndian::read_u32(&bytes))
-                }
-                SpecifiedValue::System(_) => {
-                    <%self:nongecko_unreachable>
-                        _context.cached_system_font.as_ref().unwrap().font_language_override
-                    </%self:nongecko_unreachable>
-                }
-            }
-        }
-        #[inline]
-        fn from_computed_value(computed: &computed_value::T) -> Self {
-            if computed.0 == 0 {
-                return SpecifiedValue::Normal
-            }
-            let mut buf = [0; 4];
-            BigEndian::write_u32(&mut buf, computed.0);
-            SpecifiedValue::Override(
-                if cfg!(debug_assertions) {
-                    String::from_utf8(buf.to_vec()).unwrap()
-                } else {
-                    unsafe { String::from_utf8_unchecked(buf.to_vec()) }
-                }
-            )
-        }
-    }
-
-    /// normal | <string>
-    pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-                         -> Result<SpecifiedValue, ParseError<'i>> {
-        if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
-            Ok(SpecifiedValue::Normal)
-        } else {
-            input.expect_string().map(|s| {
-                SpecifiedValue::Override(s.as_ref().to_owned())
-            }).map_err(|e| e.into())
-        }
-    }
-
-    /// Used in @font-face.
-    impl Parse for SpecifiedValue {
-        fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-                         -> Result<Self, ParseError<'i>> {
-            parse(context, input)
-        }
-    }
-
-    #[cfg(feature = "gecko")]
-    impl From<u32> for computed_value::T {
-        fn from(bits: u32) -> computed_value::T {
-            computed_value::T(bits)
-        }
-    }
-
-    #[cfg(feature = "gecko")]
-    impl From<computed_value::T> for u32 {
-        fn from(v: computed_value::T) -> u32 {
-            v.0
-        }
-    }
-</%helpers:longhand>
+${helpers.predefined_type("font-language-override",
+                          "FontLanguageOverride",
+                          products="gecko",
+                          initial_value="computed::FontLanguageOverride::zero()",
+                          initial_specified_value="specified::FontLanguageOverride::normal()",
+                          animation_value_type="discrete",
+                          extra_prefixes="moz",
+                          flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
+                          spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override")}
 
 <%helpers:longhand name="-x-lang" products="gecko" animation_value_type="none" internal="True"
                    spec="Internal (not web-exposed)">
     pub use self::computed_value::T as SpecifiedValue;
 
     pub mod computed_value {
         use Atom;
         use std::fmt;
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -1,15 +1,16 @@
 /* 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/. */
 
 //! Computed values for font properties
 
 use app_units::Au;
+use byteorder::{BigEndian, ByteOrder};
 use std::fmt;
 use style_traits::ToCss;
 use values::CSSFloat;
 use values::animated::{ToAnimatedValue, ToAnimatedZero};
 use values::computed::{Context, NonNegativeLength, ToComputedValue};
 use values::specified::font as specified;
 use values::specified::length::{FontBaseSize, NoCalcLength};
 
@@ -271,16 +272,64 @@ pub type FontVariantAlternates = specifi
 impl FontVariantAlternates {
     #[inline]
     /// Get initial value with VariantAlternatesList
     pub fn get_initial_value() -> Self {
         specified::VariantAlternatesList(vec![].into_boxed_slice())
     }
 }
 
+/// font-language-override can only have a single three-letter
+/// OpenType "language system" tag, so we should be able to compute
+/// it and store it as a 32-bit integer
+/// (see http://www.microsoft.com/typography/otspec/languagetags.htm).
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+pub struct FontLanguageOverride(pub u32);
+
+impl FontLanguageOverride {
+    #[inline]
+    /// Get computed default value of `font-language-override` with 0
+    pub fn zero() -> FontLanguageOverride {
+        FontLanguageOverride(0)
+    }
+}
+
+impl ToCss for FontLanguageOverride {
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        use std::str;
+
+        if self.0 == 0 {
+            return dest.write_str("normal")
+        }
+        let mut buf = [0; 4];
+        BigEndian::write_u32(&mut buf, self.0);
+        // Safe because we ensure it's ASCII during computing
+        let slice = if cfg!(debug_assertions) {
+            str::from_utf8(&buf).unwrap()
+        } else {
+            unsafe { str::from_utf8_unchecked(&buf) }
+        };
+        slice.trim_right().to_css(dest)
+    }
+}
+
+#[cfg(feature = "gecko")]
+impl From<u32> for FontLanguageOverride {
+    fn from(bits: u32) -> FontLanguageOverride {
+        FontLanguageOverride(bits)
+    }
+}
+
+#[cfg(feature = "gecko")]
+impl From<FontLanguageOverride> for u32 {
+    fn from(v: FontLanguageOverride) -> u32 {
+        v.0
+    }
+}
+
 impl ToComputedValue for specified::MozScriptMinSize {
     type ComputedValue = MozScriptMinSize;
 
     fn to_computed_value(&self, cx: &Context) -> MozScriptMinSize {
         // this value is used in the computation of font-size, so
         // we use the parent size
         let base_size = FontBaseSize::InheritedStyle;
         match self.0 {
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -32,17 +32,17 @@ pub use app_units::Au;
 pub use properties::animated_properties::TransitionProperty;
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::angle::Angle;
 pub use self::background::{BackgroundSize, BackgroundRepeat};
 pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
 pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
-pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
+pub use self::font::{FontLanguageOverride, MozScriptLevel, MozScriptMinSize, XTextZoom};
 pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -2,16 +2,17 @@
  * 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/. */
 
 //! Specified values for font properties
 
 #[cfg(feature = "gecko")]
 use Atom;
 use app_units::Au;
+use byteorder::{BigEndian, ByteOrder};
 use cssparser::{Parser, Token};
 use parser::{Parse, ParserContext};
 use properties::longhands::system_font::SystemFont;
 #[allow(unused_imports)]
 use std::ascii::AsciiExt;
 use std::fmt;
 use style_traits::{ToCss, StyleParseErrorKind, ParseError};
 use values::CustomIdent;
@@ -933,16 +934,112 @@ impl From<FontSynthesis> for u8 {
         }
         if v.style {
             bits |= structs::NS_FONT_SYNTHESIS_STYLE as u8;
         }
         bits
     }
 }
 
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
+/// Allows authors to explicitly specify the language system of the font,
+/// overriding the language system implied by the content language
+pub enum FontLanguageOverride {
+    /// When rendering with OpenType fonts,
+    /// the content language of the element is
+    /// used to infer the OpenType language system
+    Normal,
+    /// Single three-letter case-sensitive OpenType language system tag,
+    /// specifies the OpenType language system to be used instead of
+    /// the language system implied by the language of the element
+    Override(Box<str>),
+    /// Use system font
+    System(SystemFont)
+}
+
+impl FontLanguageOverride {
+    #[inline]
+    /// Get default value with `normal`
+    pub fn normal() -> FontLanguageOverride {
+        FontLanguageOverride::Normal
+    }
+
+    /// Get `font-language-override` with `system font`
+    pub fn system_font(f: SystemFont) -> Self {
+        FontLanguageOverride::System(f)
+    }
+
+    /// Get system font
+    pub fn get_system(&self) -> Option<SystemFont> {
+        if let FontLanguageOverride::System(s) = *self {
+            Some(s)
+        } else {
+            None
+        }
+    }
+}
+
+impl ToComputedValue for FontLanguageOverride {
+    type ComputedValue = computed::FontLanguageOverride;
+
+    #[inline]
+    fn to_computed_value(&self, _context: &Context) -> computed::FontLanguageOverride {
+        #[allow(unused_imports)] use std::ascii::AsciiExt;
+        match *self {
+            FontLanguageOverride::Normal => computed::FontLanguageOverride(0),
+            FontLanguageOverride::Override(ref lang) => {
+                if lang.is_empty() || lang.len() > 4 || !lang.is_ascii() {
+                    return computed::FontLanguageOverride(0)
+                }
+                let mut computed_lang = lang.to_string();
+                while computed_lang.len() < 4 {
+                    computed_lang.push(' ');
+                }
+                let bytes = computed_lang.into_bytes();
+                computed::FontLanguageOverride(BigEndian::read_u32(&bytes))
+            }
+            FontLanguageOverride::System(_) => {
+                #[cfg(feature = "gecko")] {
+                    _context.cached_system_font.as_ref().unwrap().font_language_override
+                }
+                #[cfg(feature = "servo")] {
+                    unreachable!()
+                }
+            }
+        }
+    }
+    #[inline]
+    fn from_computed_value(computed: &computed::FontLanguageOverride) -> Self {
+        if computed.0 == 0 {
+            return FontLanguageOverride::Normal
+        }
+        let mut buf = [0; 4];
+        BigEndian::write_u32(&mut buf, computed.0);
+        FontLanguageOverride::Override(
+            if cfg!(debug_assertions) {
+                String::from_utf8(buf.to_vec()).unwrap()
+            } else {
+                unsafe { String::from_utf8_unchecked(buf.to_vec()) }
+            }.into_boxed_str()
+        )
+    }
+}
+
+impl Parse for FontLanguageOverride {
+    /// normal | <string>
+    fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<FontLanguageOverride, ParseError<'i>> {
+        if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
+            return Ok(FontLanguageOverride::Normal)
+        }
+
+        let string = input.expect_string()?;
+        Ok(FontLanguageOverride::Override(string.as_ref().to_owned().into_boxed_str()))
+    }
+}
+
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
 /// text-zoom. Enable if true, disable if false
 pub struct XTextZoom(pub bool);
 
 impl Parse for XTextZoom {
     fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<XTextZoom, ParseError<'i>> {
         debug_assert!(false, "Should be set directly by presentation attributes only.");
         Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -26,17 +26,17 @@ use values::specified::calc::CalcNode;
 pub use properties::animated_properties::TransitionProperty;
 pub use self::angle::Angle;
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::background::{BackgroundRepeat, BackgroundSize};
 pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
 pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
 pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
-pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
+pub use self::font::{FontLanguageOverride, MozScriptLevel, MozScriptMinSize, XTextZoom};
 pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};