diff --git a/Cargo.lock b/Cargo.lock index 9e00ee76e97..e01e74c124a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2799,6 +2799,7 @@ name = "style_tests" version = "0.0.1" dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index e6aab102506..970b6a929a0 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1296,12 +1296,47 @@ fn static_assert() { skip_font_longhands = """font-family font-size font-size-adjust font-weight font-synthesis -x-lang font-variant-alternates font-variant-east-asian font-variant-ligatures - font-variant-numeric font-language-override""" + font-variant-numeric font-language-override + font-feature-settings""" %> <%self:impl_trait style_struct_name="Font" skip_longhands="${skip_font_longhands}" skip_additionals="*"> + pub fn set_font_feature_settings(&mut self, v: longhands::font_feature_settings::computed_value::T) { + use properties::longhands::font_feature_settings::computed_value::T; + + let current_settings = &mut self.gecko.mFont.fontFeatureSettings; + current_settings.clear_pod(); + + match v { + T::Normal => unsafe { current_settings.set_len_pod(0) }, + + T::Tag(feature_settings) => { + unsafe { current_settings.set_len_pod(feature_settings.len() as u32) }; + + for (current, feature) in current_settings.iter_mut().zip(feature_settings) { + current.mTag = feature.tag; + current.mValue = feature.value; + } + } + }; + } + + pub fn copy_font_feature_settings_from(&mut self, other: &Self ) { + let current_settings = &mut self.gecko.mFont.fontFeatureSettings; + let feature_settings = &other.gecko.mFont.fontFeatureSettings; + let settings_length = feature_settings.len() as u32; + + current_settings.clear_pod(); + unsafe { current_settings.set_len_pod(settings_length) }; + + for (current, feature) in current_settings.iter_mut().zip(feature_settings.iter()) { + current.mTag = feature.mTag; + current.mValue = feature.mValue; + } + } + pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) { use properties::longhands::font_family::computed_value::FontFamily; use gecko_bindings::structs::FontFamilyType; diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 842b3279d90..761dd95e025 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -1754,7 +1754,7 @@ ${helpers.single_keyword_system("font-variant-position", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position", animation_value_type="none")} -<%helpers:longhand name="font-feature-settings" products="none" animation_value_type="none" extra_prefixes="moz" +<%helpers:longhand name="font-feature-settings" products="gecko" animation_value_type="none" extra_prefixes="moz" spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings"> use std::fmt; use style_traits::ToCss; @@ -1781,8 +1781,8 @@ ${helpers.single_keyword_system("font-variant-position", #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct FeatureTagValue { - pub tag: String, - pub value: i32 + pub tag: u32, + pub value: u32 } impl ToCss for T { @@ -1806,10 +1806,17 @@ ${helpers.single_keyword_system("font-variant-position", impl ToCss for FeatureTagValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + use std::str; + use byteorder::{WriteBytesExt, NativeEndian}; + + let mut raw: Vec = vec!(); + raw.write_u32::(self.tag).unwrap(); + let str_print = str::from_utf8(&raw).unwrap_or_default(); + match self.value { - 1 => write!(dest, "\"{}\"", self.tag), - 0 => write!(dest, "\"{}\" off", self.tag), - x => write!(dest, "\"{}\" {}", self.tag, x) + 1 => write!(dest, "\"{}\"", str_print), + 0 => write!(dest, "\"{}\" off",str_print), + x => write!(dest, "\"{}\" {}", str_print, x) } } } @@ -1818,6 +1825,11 @@ ${helpers.single_keyword_system("font-variant-position", /// https://www.w3.org/TR/css-fonts-3/#propdef-font-feature-settings /// [ on | off | ] fn parse(_context: &ParserContext, input: &mut Parser) -> Result { + use std::io::Cursor; + use std::str; + use std::ops::Deref; + use byteorder::{ReadBytesExt, NativeEndian}; + let tag = try!(input.expect_string()); // allowed strings of length 4 containing chars: @@ -1827,22 +1839,25 @@ ${helpers.single_keyword_system("font-variant-position", return Err(()) } + let mut raw = Cursor::new(tag.as_bytes()); + let u_tag = raw.read_u32::().unwrap(); + if let Ok(value) = input.try(|input| input.expect_integer()) { // handle integer, throw if it is negative if value >= 0 { - Ok(FeatureTagValue { tag: tag.into_owned(), value: value }) + Ok(FeatureTagValue { tag: u_tag, value: value as u32 }) } else { Err(()) } } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) { // on is an alias for '1' - Ok(FeatureTagValue { tag: tag.into_owned(), value: 1 }) + Ok(FeatureTagValue { tag: u_tag, value: 1 }) } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) { // off is an alias for '0' - Ok(FeatureTagValue { tag: tag.into_owned(), value: 0 }) + Ok(FeatureTagValue { tag: u_tag, value: 0 }) } else { // empty value is an alias for '1' - Ok(FeatureTagValue { tag:tag.into_owned(), value: 1 }) + Ok(FeatureTagValue { tag: u_tag, value: 1 }) } } } diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml index 09e0231931b..6a5dc7fdcbd 100644 --- a/tests/unit/style/Cargo.toml +++ b/tests/unit/style/Cargo.toml @@ -13,6 +13,7 @@ doctest = false testing = ["style/testing"] [dependencies] +byteorder = "1.0" app_units = "0.4" cssparser = "0.13" euclid = "0.11" diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index 0c2d9c8b53e..9d6d2b8e8be 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -6,6 +6,7 @@ #![feature(plugin, test)] extern crate app_units; +extern crate byteorder; extern crate cssparser; extern crate euclid; #[macro_use] extern crate html5ever; diff --git a/tests/unit/style/parsing/font.rs b/tests/unit/style/parsing/font.rs index cdb64961483..44bf1d4b47c 100644 --- a/tests/unit/style/parsing/font.rs +++ b/tests/unit/style/parsing/font.rs @@ -10,38 +10,47 @@ use style_traits::ToCss; #[test] fn font_feature_settings_should_parse_properly() { + use byteorder::{ReadBytesExt, NativeEndian}; + use std::io::Cursor; + let normal = parse_longhand!(font_feature_settings, "normal"); let normal_computed = computed_value::T::Normal; assert_eq!(normal, normal_computed); + let mut a_d_bytes = Cursor::new(b"abcd"); + let mut e_h_bytes = Cursor::new(b"efgh"); + + let abcd = a_d_bytes.read_u32::().unwrap(); + let efgh = e_h_bytes.read_u32::().unwrap(); + let on = parse_longhand!(font_feature_settings, "\"abcd\" on"); let on_computed = computed_value::T::Tag(vec![ - FeatureTagValue { tag: String::from("abcd"), value: 1 } + FeatureTagValue { tag: abcd, value: 1 } ]); assert_eq!(on, on_computed); let off = parse_longhand!(font_feature_settings, "\"abcd\" off"); let off_computed = computed_value::T::Tag(vec![ - FeatureTagValue { tag: String::from("abcd"), value: 0 } + FeatureTagValue { tag: abcd, value: 0 } ]); assert_eq!(off, off_computed); let no_value = parse_longhand!(font_feature_settings, "\"abcd\""); let no_value_computed = computed_value::T::Tag(vec![ - FeatureTagValue { tag: String::from("abcd"), value: 1 } + FeatureTagValue { tag: abcd, value: 1 } ]); assert_eq!(no_value, no_value_computed); let pos_integer = parse_longhand!(font_feature_settings, "\"abcd\" 100"); let pos_integer_computed = computed_value::T::Tag(vec![ - FeatureTagValue { tag: String::from("abcd"), value: 100 } + FeatureTagValue { tag: abcd, value: 100 } ]); assert_eq!(pos_integer, pos_integer_computed); let multiple = parse_longhand!(font_feature_settings, "\"abcd\" off, \"efgh\""); let multiple_computed = computed_value::T::Tag(vec![ - FeatureTagValue { tag: String::from("abcd"), value: 0 }, - FeatureTagValue { tag: String::from("efgh"), value: 1 } + FeatureTagValue { tag: abcd, value: 0 }, + FeatureTagValue { tag: efgh, value: 1 } ]); assert_eq!(multiple, multiple_computed); }