mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Use the Parse trait for @font-face
parsing.
This commit is contained in:
parent
7724bb01a3
commit
2b83d844da
3 changed files with 88 additions and 73 deletions
|
@ -11,7 +11,6 @@
|
|||
use computed_values::font_family::FontFamily;
|
||||
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use parser::{ParserContext, log_css_error, Parse};
|
||||
use properties::longhands::font_family::parse_one_family;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use style_traits::ToCss;
|
||||
|
@ -181,40 +180,44 @@ impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
|
|||
|
||||
fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<(), ()> {
|
||||
match_ignore_ascii_case! { name,
|
||||
"font-family" => {
|
||||
self.rule.family = parse_one_family(input)?;
|
||||
},
|
||||
"src" => {
|
||||
self.rule.sources = input.parse_comma_separated(|input| {
|
||||
parse_one_src(self.context, input)
|
||||
})?;
|
||||
},
|
||||
"font-family" => self.rule.family = Parse::parse(self.context, input)?,
|
||||
"src" => self.rule.sources = Parse::parse(self.context, input)?,
|
||||
_ => return Err(())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_one_src(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
|
||||
if input.try(|input| input.expect_function_matching("local")).is_ok() {
|
||||
return Ok(Source::Local(try!(input.parse_nested_block(parse_one_family))))
|
||||
impl Parse for Vec<Source> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
input.parse_comma_separated(|input| Source::parse(context, input))
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Source {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
|
||||
if input.try(|input| input.expect_function_matching("local")).is_ok() {
|
||||
return input.parse_nested_block(|input| {
|
||||
FontFamily::parse(context, input)
|
||||
}).map(Source::Local)
|
||||
}
|
||||
|
||||
let url = SpecifiedUrl::parse(context, input)?;
|
||||
|
||||
// Parsing optional format()
|
||||
let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
|
||||
input.parse_nested_block(|input| {
|
||||
input.parse_comma_separated(|input| {
|
||||
Ok(input.expect_string()?.into_owned())
|
||||
})
|
||||
})?
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
Ok(Source::Url(UrlSource {
|
||||
url: url,
|
||||
format_hints: format_hints,
|
||||
}))
|
||||
}
|
||||
|
||||
let url = try!(SpecifiedUrl::parse(context, input));
|
||||
|
||||
// Parsing optional format()
|
||||
let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
input.parse_comma_separated(|input| {
|
||||
Ok((try!(input.expect_string())).into_owned())
|
||||
})
|
||||
}))
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
Ok(Source::Url(UrlSource {
|
||||
url: url,
|
||||
format_hints: format_hints,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -107,56 +107,66 @@
|
|||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(vec![FontFamily::Generic(atom!("serif"))])
|
||||
}
|
||||
|
||||
/// <family-name>#
|
||||
/// <family-name> = <string> | [ <ident>+ ]
|
||||
/// TODO: <generic-family>
|
||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
input.parse_comma_separated(parse_one_family).map(SpecifiedValue)
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
Vec::<FontFamily>::parse(context, input).map(SpecifiedValue)
|
||||
}
|
||||
pub fn parse_one_family(input: &mut Parser) -> Result<FontFamily, ()> {
|
||||
if let Ok(value) = input.try(|input| input.expect_string()) {
|
||||
return Ok(FontFamily::FamilyName(Atom::from(&*value)))
|
||||
}
|
||||
let first_ident = try!(input.expect_ident());
|
||||
|
||||
// FIXME(bholley): The fast thing to do here would be to look up the
|
||||
// string (as lowercase) in the static atoms table. We don't have an
|
||||
// API to do that yet though, so we do the simple thing for now.
|
||||
let mut css_wide_keyword = false;
|
||||
match_ignore_ascii_case! { first_ident,
|
||||
"serif" => return Ok(FontFamily::Generic(atom!("serif"))),
|
||||
"sans-serif" => return Ok(FontFamily::Generic(atom!("sans-serif"))),
|
||||
"cursive" => return Ok(FontFamily::Generic(atom!("cursive"))),
|
||||
"fantasy" => return Ok(FontFamily::Generic(atom!("fantasy"))),
|
||||
"monospace" => return Ok(FontFamily::Generic(atom!("monospace"))),
|
||||
impl Parse for Vec<FontFamily> {
|
||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
input.parse_comma_separated(|input| FontFamily::parse(context, input))
|
||||
}
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-fonts/#propdef-font-family
|
||||
// "Font family names that happen to be the same as a keyword value
|
||||
// (‘inherit’, ‘serif’, ‘sans-serif’, ‘monospace’, ‘fantasy’, and ‘cursive’)
|
||||
// must be quoted to prevent confusion with the keywords with the same names.
|
||||
// The keywords ‘initial’ and ‘default’ are reserved for future use
|
||||
// and must also be quoted when used as font names.
|
||||
// UAs must not consider these keywords as matching the <family-name> type."
|
||||
"inherit" => css_wide_keyword = true,
|
||||
"initial" => css_wide_keyword = true,
|
||||
"unset" => css_wide_keyword = true,
|
||||
"default" => css_wide_keyword = true,
|
||||
_ => {}
|
||||
}
|
||||
impl Parse for FontFamily {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
if let Ok(value) = input.try(|input| input.expect_string()) {
|
||||
return Ok(FontFamily::FamilyName(Atom::from(&*value)))
|
||||
}
|
||||
let first_ident = try!(input.expect_ident());
|
||||
|
||||
let mut value = first_ident.into_owned();
|
||||
// These keywords are not allowed by themselves.
|
||||
// The only way this value can be valid with with another keyword.
|
||||
if css_wide_keyword {
|
||||
let ident = input.expect_ident()?;
|
||||
value.push_str(" ");
|
||||
value.push_str(&ident);
|
||||
// FIXME(bholley): The fast thing to do here would be to look up the
|
||||
// string (as lowercase) in the static atoms table. We don't have an
|
||||
// API to do that yet though, so we do the simple thing for now.
|
||||
let mut css_wide_keyword = false;
|
||||
match_ignore_ascii_case! { first_ident,
|
||||
"serif" => return Ok(FontFamily::Generic(atom!("serif"))),
|
||||
"sans-serif" => return Ok(FontFamily::Generic(atom!("sans-serif"))),
|
||||
"cursive" => return Ok(FontFamily::Generic(atom!("cursive"))),
|
||||
"fantasy" => return Ok(FontFamily::Generic(atom!("fantasy"))),
|
||||
"monospace" => return Ok(FontFamily::Generic(atom!("monospace"))),
|
||||
|
||||
// https://drafts.csswg.org/css-fonts/#propdef-font-family
|
||||
// "Font family names that happen to be the same as a keyword value
|
||||
// (‘inherit’, ‘serif’, ‘sans-serif’, ‘monospace’, ‘fantasy’, and ‘cursive’)
|
||||
// must be quoted to prevent confusion with the keywords with the same names.
|
||||
// The keywords ‘initial’ and ‘default’ are reserved for future use
|
||||
// and must also be quoted when used as font names.
|
||||
// UAs must not consider these keywords as matching the <family-name> type."
|
||||
"inherit" => css_wide_keyword = true,
|
||||
"initial" => css_wide_keyword = true,
|
||||
"unset" => css_wide_keyword = true,
|
||||
"default" => css_wide_keyword = true,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut value = first_ident.into_owned();
|
||||
// These keywords are not allowed by themselves.
|
||||
// The only way this value can be valid with with another keyword.
|
||||
if css_wide_keyword {
|
||||
let ident = input.expect_ident()?;
|
||||
value.push_str(" ");
|
||||
value.push_str(&ident);
|
||||
}
|
||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||
value.push_str(" ");
|
||||
value.push_str(&ident);
|
||||
}
|
||||
Ok(FontFamily::FamilyName(Atom::from(value)))
|
||||
}
|
||||
while let Ok(ident) = input.try(|input| input.expect_ident()) {
|
||||
value.push_str(" ");
|
||||
value.push_str(&ident);
|
||||
}
|
||||
Ok(FontFamily::FamilyName(Atom::from(value)))
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
<%helpers:shorthand name="font" sub_properties="font-style font-variant font-weight font-stretch
|
||||
font-size line-height font-family"
|
||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
|
||||
use parser::Parse;
|
||||
use properties::longhands::{font_style, font_variant, font_weight, font_stretch};
|
||||
use properties::longhands::{font_size, line_height, font_family};
|
||||
use properties::longhands::font_family::computed_value::FontFamily;
|
||||
|
||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||
let mut nb_normals = 0;
|
||||
|
@ -64,7 +66,7 @@
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let family = try!(input.parse_comma_separated(font_family::parse_one_family));
|
||||
let family = Vec::<FontFamily>::parse(context, input)?;
|
||||
Ok(Longhands {
|
||||
font_style: style,
|
||||
font_variant: variant,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue