Auto merge of #17981 - heycam:family-serialization, r=emilio

style: Preserve font-family identifier sequence when serializing.

Reviewed by Emilio in https://bugzilla.mozilla.org/show_bug.cgi?id=1384398.
This commit is contained in:
bors-servo 2017-08-05 04:56:08 -05:00 committed by GitHub
commit 6cb790f8eb
4 changed files with 59 additions and 26 deletions

View file

@ -2181,7 +2181,7 @@ fn static_assert() {
} }
pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) { pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) {
use properties::longhands::font_family::computed_value::FontFamily; use properties::longhands::font_family::computed_value::{FontFamily, FamilyNameSyntax};
let list = &mut self.gecko.mFont.fontlist; let list = &mut self.gecko.mFont.fontlist;
unsafe { Gecko_FontFamilyList_Clear(list); } unsafe { Gecko_FontFamilyList_Clear(list); }
@ -2191,7 +2191,8 @@ fn static_assert() {
for family in &v.0 { for family in &v.0 {
match *family { match *family {
FontFamily::FamilyName(ref f) => { FontFamily::FamilyName(ref f) => {
unsafe { Gecko_FontFamilyList_AppendNamed(list, f.name.as_ptr(), f.quoted); } let quoted = matches!(f.syntax, FamilyNameSyntax::Quoted);
unsafe { Gecko_FontFamilyList_AppendNamed(list, f.name.as_ptr(), quoted); }
} }
FontFamily::Generic(ref name) => { FontFamily::Generic(ref name) => {
let (family_type, generic) = FontFamily::generic(name); let (family_type, generic) = FontFamily::generic(name);
@ -2222,7 +2223,8 @@ fn static_assert() {
} }
pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T { pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T {
use properties::longhands::font_family::computed_value::{FontFamily, FamilyName}; use cssparser::serialize_identifier;
use properties::longhands::font_family::computed_value::{FontFamily, FamilyName, FamilyNameSyntax};
use gecko_bindings::structs::FontFamilyType; use gecko_bindings::structs::FontFamilyType;
use gecko_string_cache::Atom; use gecko_string_cache::Atom;
@ -2235,13 +2237,18 @@ fn static_assert() {
FontFamilyType::eFamily_cursive => FontFamily::Generic(atom!("cursive")), FontFamilyType::eFamily_cursive => FontFamily::Generic(atom!("cursive")),
FontFamilyType::eFamily_fantasy => FontFamily::Generic(atom!("fantasy")), FontFamilyType::eFamily_fantasy => FontFamily::Generic(atom!("fantasy")),
FontFamilyType::eFamily_moz_fixed => FontFamily::Generic(Atom::from("-moz-fixed")), FontFamilyType::eFamily_moz_fixed => FontFamily::Generic(Atom::from("-moz-fixed")),
FontFamilyType::eFamily_named => FontFamily::FamilyName(FamilyName { FontFamilyType::eFamily_named => {
name: (&*gecko_font_family_name.mName).into(), let name = Atom::from(&*gecko_font_family_name.mName);
quoted: false let mut serialization = String::new();
}), serialize_identifier(&name.to_string(), &mut serialization).unwrap();
FontFamily::FamilyName(FamilyName {
name: name.clone(),
syntax: FamilyNameSyntax::Identifiers(serialization),
})
},
FontFamilyType::eFamily_named_quoted => FontFamily::FamilyName(FamilyName { FontFamilyType::eFamily_named_quoted => FontFamily::FamilyName(FamilyName {
name: (&*gecko_font_family_name.mName).into(), name: (&*gecko_font_family_name.mName).into(),
quoted: true syntax: FamilyNameSyntax::Quoted,
}), }),
x => panic!("Found unexpected font FontFamilyType: {:?}", x), x => panic!("Found unexpected font FontFamilyType: {:?}", x),
} }

View file

@ -96,7 +96,20 @@ macro_rules! impl_gecko_keyword_conversions {
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct FamilyName { pub struct FamilyName {
pub name: Atom, pub name: Atom,
pub quoted: bool, pub syntax: FamilyNameSyntax,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum FamilyNameSyntax {
/// The family name was specified in a quoted form, e.g. "Font Name"
/// or 'Font Name'.
Quoted,
/// The family name was specified in an unquoted form as a sequence of
/// identifiers. The `String` is the serialization of the sequence of
/// identifiers.
Identifiers(String),
} }
impl FontFamily { impl FontFamily {
@ -139,7 +152,7 @@ macro_rules! impl_gecko_keyword_conversions {
// quoted by default. // quoted by default.
FontFamily::FamilyName(FamilyName { FontFamily::FamilyName(FamilyName {
name: input, name: input,
quoted: true, syntax: FamilyNameSyntax::Quoted,
}) })
} }
@ -148,7 +161,7 @@ macro_rules! impl_gecko_keyword_conversions {
if let Ok(value) = input.try(|i| i.expect_string_cloned()) { if let Ok(value) = input.try(|i| i.expect_string_cloned()) {
return Ok(FontFamily::FamilyName(FamilyName { return Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(&*value), name: Atom::from(&*value),
quoted: true, syntax: FamilyNameSyntax::Quoted,
})) }))
} }
let first_ident = input.expect_ident()?.clone(); let first_ident = input.expect_ident()?.clone();
@ -182,20 +195,28 @@ macro_rules! impl_gecko_keyword_conversions {
} }
let mut value = first_ident.as_ref().to_owned(); let mut value = first_ident.as_ref().to_owned();
let mut serialization = String::new();
serialize_identifier(&first_ident, &mut serialization).unwrap();
// These keywords are not allowed by themselves. // These keywords are not allowed by themselves.
// The only way this value can be valid with with another keyword. // The only way this value can be valid with with another keyword.
if css_wide_keyword { if css_wide_keyword {
let ident = input.expect_ident()?; let ident = input.expect_ident()?;
value.push_str(" "); value.push(' ');
value.push_str(&ident); value.push_str(&ident);
serialization.push(' ');
serialize_identifier(&ident, &mut serialization).unwrap();
} }
while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) {
value.push_str(" "); value.push(' ');
value.push_str(&ident); value.push_str(&ident);
serialization.push(' ');
serialize_identifier(&ident, &mut serialization).unwrap();
} }
println!("serialization: {}", serialization);
Ok(FontFamily::FamilyName(FamilyName { Ok(FontFamily::FamilyName(FamilyName {
name: Atom::from(value), name: Atom::from(value),
quoted: false, syntax: FamilyNameSyntax::Identifiers(serialization),
})) }))
} }
@ -229,12 +250,17 @@ macro_rules! impl_gecko_keyword_conversions {
impl ToCss for FamilyName { impl ToCss for FamilyName {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
if self.quoted { match self.syntax {
dest.write_char('"')?; FamilyNameSyntax::Quoted => {
write!(CssStringWriter::new(dest), "{}", self.name)?; dest.write_char('"')?;
dest.write_char('"') write!(CssStringWriter::new(dest), "{}", self.name)?;
} else { dest.write_char('"')
serialize_identifier(&*self.name.to_string(), dest) }
FamilyNameSyntax::Identifiers(ref serialization) => {
// Note that `serialization` is already escaped/
// serialized appropriately.
dest.write_str(&*serialization)
}
} }
} }
} }
@ -2508,7 +2534,7 @@ ${helpers.single_keyword("-moz-math-variant",
use properties::longhands::font_family::computed_value::*; use properties::longhands::font_family::computed_value::*;
FontFamily::FamilyName(FamilyName { FontFamily::FamilyName(FamilyName {
name: (&*font.mName).into(), name: (&*font.mName).into(),
quoted: true syntax: FamilyNameSyntax::Quoted,
}) })
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
let weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); let weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight);

View file

@ -5,7 +5,7 @@
use cssparser::SourceLocation; use cssparser::SourceLocation;
use gfx::font_cache_thread::FontCacheThread; use gfx::font_cache_thread::FontCacheThread;
use ipc_channel::ipc; use ipc_channel::ipc;
use style::computed_values::font_family::FamilyName; use style::computed_values::font_family::{FamilyName, FamilyNameSyntax};
use style::font_face::{FontFaceRuleData, Source}; use style::font_face::{FontFaceRuleData, Source};
#[test] #[test]
@ -15,11 +15,11 @@ fn test_local_web_font() {
let font_cache_thread = FontCacheThread::new(inp_chan, None); let font_cache_thread = FontCacheThread::new(inp_chan, None);
let family_name = FamilyName { let family_name = FamilyName {
name: From::from("test family"), name: From::from("test family"),
quoted: true, syntax: FamilyNameSyntax::Quoted,
}; };
let variant_name = FamilyName { let variant_name = FamilyName {
name: From::from("test font face"), name: From::from("test font face"),
quoted: true, syntax: FamilyNameSyntax::Quoted,
}; };
let font_face_rule = FontFaceRuleData { let font_face_rule = FontFaceRuleData {
family: Some(family_name.clone()), family: Some(family_name.clone()),

View file

@ -14,7 +14,7 @@ use servo_url::ServoUrl;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use style::computed_values::font_family::FamilyName; use style::computed_values::font_family::{FamilyName, FamilyNameSyntax};
use style::context::QuirksMode; use style::context::QuirksMode;
use style::error_reporting::{ParseErrorReporter, ContextualParseError}; use style::error_reporting::{ParseErrorReporter, ContextualParseError};
use style::media_queries::MediaList; use style::media_queries::MediaList;
@ -254,7 +254,7 @@ fn test_parse_stylesheet() {
CssRule::FontFeatureValues(Arc::new(stylesheet.shared_lock.wrap(FontFeatureValuesRule { CssRule::FontFeatureValues(Arc::new(stylesheet.shared_lock.wrap(FontFeatureValuesRule {
family_names: vec![FamilyName { family_names: vec![FamilyName {
name: Atom::from("test"), name: Atom::from("test"),
quoted: false, syntax: FamilyNameSyntax::Identifiers(String::from("test")),
}], }],
swash: vec![ swash: vec![
FFVDeclaration { FFVDeclaration {