diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 5130f03e45a..f320bb0e201 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -8,7 +8,8 @@ #![deny(missing_docs)] -#[cfg(feature = "gecko")] use computed_values::{font_style, font_weight, font_stretch}; +#[cfg(feature = "gecko")] +use computed_values::{font_style, font_weight, font_stretch}; use computed_values::font_family::FamilyName; use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; use parser::{ParserContext, log_css_error, Parse}; @@ -141,12 +142,6 @@ impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> { type AtRule = (); } -impl Parse for Vec { - fn parse(context: &ParserContext, input: &mut Parser) -> Result { - input.parse_comma_separated(|input| Source::parse(context, input)) - } -} - impl Parse for Source { fn parse(context: &ParserContext, input: &mut Parser) -> Result { if input.try(|input| input.expect_function_matching("local")).is_ok() { @@ -301,6 +296,11 @@ font_face_descriptors! { /// The stretch of this font face "font-stretch" stretch: font_stretch::T = font_stretch::T::normal, + + /// The ranges of code points outside of which this font face should not be used. + "unicode-range" unicode_range: Vec = vec![ + unicode_range::Range { start: 0, end: unicode_range::MAX } + ], ] } @@ -316,3 +316,51 @@ font_face_descriptors! { optional descriptors = [ ] } + +/// https://drafts.csswg.org/css-fonts/#unicode-range-desc +#[cfg(feature = "gecko")] +pub mod unicode_range { + use cssparser::{Parser, Token}; + use parser::{ParserContext, Parse}; + use std::fmt; + use style_traits::{ToCss, CommaSeparated}; + + /// Maximum value of the end of a range + pub const MAX: u32 = ::std::char::MAX as u32; + + /// A single range: https://drafts.csswg.org/css-fonts/#urange-value + #[derive(Debug, PartialEq, Eq)] + pub struct Range { + /// Start of the range, inclusive + pub start: u32, + + /// End of the range, inclusive + pub end: u32, + } + + impl CommaSeparated for Range {} + + impl Parse for Range { + fn parse(_context: &ParserContext, input: &mut Parser) -> Result { + // FIXME: The unicode-range token has been removed from the CSS Syntax spec, + // cssparser should be updated accordingly + // and implement https://drafts.csswg.org/css-syntax/#urange instead + match input.next() { + Ok(Token::UnicodeRange(start, end)) => { + if end <= MAX && start <= end { + Ok(Range { start: start, end: end }) + } else { + Err(()) + } + } + _ => Err(()) + } + } + } + + impl ToCss for Range { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + Token::UnicodeRange(self.start, self.end).to_css(dest) + } + } +} diff --git a/components/style/parser.rs b/components/style/parser.rs index 60efcb8a4be..e325547b368 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -11,6 +11,7 @@ use error_reporting::ParseErrorReporter; #[cfg(feature = "gecko")] use gecko_bindings::sugar::refptr::{GeckoArcPrincipal, GeckoArcURI}; use servo_url::ServoUrl; +use style_traits::CommaSeparated; use stylesheets::{MemoryHoleReporter, Origin}; /// Extra data that the style backend may need to parse stylesheets. @@ -102,3 +103,9 @@ pub trait Parse : Sized { /// Returns an error on failure. fn parse(context: &ParserContext, input: &mut Parser) -> Result; } + +impl Parse for Vec where T: Parse + CommaSeparated { + fn parse(context: &ParserContext, input: &mut Parser) -> Result { + input.parse_comma_separated(|input| T::parse(context, input)) + } +}