mirror of
https://github.com/servo/servo.git
synced 2025-07-02 04:53:39 +01:00
stylo: Support font-family presentation attribute
This commit is contained in:
parent
404ebf5b3a
commit
afccbf4a8c
3 changed files with 74 additions and 64 deletions
|
@ -19,7 +19,7 @@
|
||||||
no_viewport_percentage!(SpecifiedValue);
|
no_viewport_percentage!(SpecifiedValue);
|
||||||
|
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use cssparser::CssStringWriter;
|
use cssparser::{CssStringWriter, Parser};
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use Atom;
|
use Atom;
|
||||||
use style_traits::ToCss;
|
use style_traits::ToCss;
|
||||||
|
@ -73,6 +73,53 @@
|
||||||
}
|
}
|
||||||
FontFamily::FamilyName(FamilyName(input))
|
FontFamily::FamilyName(FamilyName(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a font-family value
|
||||||
|
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||||
|
if let Ok(value) = input.try(|input| input.expect_string()) {
|
||||||
|
return Ok(FontFamily::FamilyName(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"))),
|
||||||
|
|
||||||
|
// 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(FamilyName(Atom::from(value))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for FamilyName {
|
impl ToCss for FamilyName {
|
||||||
|
@ -119,75 +166,27 @@
|
||||||
/// <family-name>#
|
/// <family-name>#
|
||||||
/// <family-name> = <string> | [ <ident>+ ]
|
/// <family-name> = <string> | [ <ident>+ ]
|
||||||
/// TODO: <generic-family>
|
/// TODO: <generic-family>
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
Vec::<FontFamily>::parse(context, input).map(SpecifiedValue)
|
SpecifiedValue::parse(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Vec<FontFamily> {
|
impl SpecifiedValue {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
pub fn parse(input: &mut Parser) -> Result<Self, ()> {
|
||||||
input.parse_comma_separated(|input| FontFamily::parse(context, input))
|
input.parse_comma_separated(|input| FontFamily::parse(input)).map(SpecifiedValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
|
/// `FamilyName::parse` is based on `FontFamily::parse` and not the other way around
|
||||||
/// because we want the former to exclude generic family keywords.
|
/// because we want the former to exclude generic family keywords.
|
||||||
impl Parse for FamilyName {
|
impl Parse for FamilyName {
|
||||||
fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
fn parse(_: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||||
match FontFamily::parse(context, input) {
|
match FontFamily::parse(input) {
|
||||||
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
||||||
Ok(FontFamily::Generic(_)) |
|
Ok(FontFamily::Generic(_)) |
|
||||||
Err(()) => Err(())
|
Err(()) => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(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"))),
|
|
||||||
|
|
||||||
// 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(FamilyName(Atom::from(value))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</%helpers:longhand>
|
</%helpers:longhand>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
${'font-variant-position' if product == 'gecko' else ''}
|
${'font-variant-position' if product == 'gecko' else ''}
|
||||||
${'font-language-override' if product == 'none' else ''}"
|
${'font-language-override' if product == 'none' else ''}"
|
||||||
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
|
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_style, font_variant, font_weight, font_stretch};
|
||||||
use properties::longhands::{font_size, line_height, font_family};
|
use properties::longhands::{font_size, line_height};
|
||||||
use properties::longhands::font_family::computed_value::FontFamily;
|
use properties::longhands::font_family::SpecifiedValue as FontFamily;
|
||||||
|
|
||||||
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result<Longhands, ()> {
|
||||||
let mut nb_normals = 0;
|
let mut nb_normals = 0;
|
||||||
|
@ -71,7 +70,7 @@
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let family = Vec::<FontFamily>::parse(context, input)?;
|
let family = FontFamily::parse(input)?;
|
||||||
Ok(Longhands {
|
Ok(Longhands {
|
||||||
font_style: style,
|
font_style: style,
|
||||||
font_variant: variant,
|
font_variant: variant,
|
||||||
|
@ -79,7 +78,7 @@
|
||||||
font_stretch: stretch,
|
font_stretch: stretch,
|
||||||
font_size: size,
|
font_size: size,
|
||||||
line_height: line_height,
|
line_height: line_height,
|
||||||
font_family: Some(font_family::SpecifiedValue(family)),
|
font_family: Some(family),
|
||||||
% if product == "gecko":
|
% if product == "gecko":
|
||||||
font_size_adjust: None,
|
font_size_adjust: None,
|
||||||
font_kerning: None,
|
font_kerning: None,
|
||||||
|
|
|
@ -1150,10 +1150,22 @@ pub extern "C" fn Servo_DeclarationBlock_SetColorValue(declarations:
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(_:
|
pub extern "C" fn Servo_DeclarationBlock_SetFontFamily(declarations:
|
||||||
RawServoDeclarationBlockBorrowed,
|
RawServoDeclarationBlockBorrowed,
|
||||||
_: *const nsAString) {
|
value: *const nsAString) {
|
||||||
|
use cssparser::Parser;
|
||||||
|
use style::properties::{DeclaredValue, PropertyDeclaration};
|
||||||
|
use style::properties::longhands::font_family::SpecifiedValue as FontFamily;
|
||||||
|
|
||||||
|
let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
|
||||||
|
let string = unsafe { (*value).to_string() };
|
||||||
|
let mut parser = Parser::new(&string);
|
||||||
|
if let Ok(family) = FontFamily::parse(&mut parser) {
|
||||||
|
if parser.is_exhausted() {
|
||||||
|
let decl = PropertyDeclaration::FontFamily(DeclaredValue::Value(family));
|
||||||
|
declarations.write().declarations.push((decl, Default::default()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue