From caa15ab6a7d9990a239f52fac8198f0e24e71aa5 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Tue, 13 Feb 2018 09:17:19 +1100 Subject: [PATCH] Output unquoted family name as a series of identifiers. It tries to serialize unquoted family names as a series of identifiers. For family names which contain special white spaces like leading white space, trailing white space, and consective white spaces, unquoted names are marked quoted in parsing to avoid complicating serialization code. --- components/style/values/computed/font.rs | 43 ++++++++++++++---------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 646f91155f7..63b18bb3512 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -286,10 +286,20 @@ impl ToCss for FamilyName { write!(CssStringWriter::new(dest), "{}", self.name)?; dest.write_char('"') } - FamilyNameSyntax::Identifiers(ref serialization) => { - // Note that `serialization` is already escaped/ - // serialized appropriately. - dest.write_str(&*serialization) + FamilyNameSyntax::Identifiers => { + let mut first = true; + for ident in self.name.to_string().split(' ') { + if first { + first = false; + } else { + dest.write_char(' ')?; + } + debug_assert!(!ident.is_empty(), "Family name with leading, \ + trailing, or consecutive white spaces should \ + have been marked quoted by the parser"); + serialize_identifier(ident, dest)?; + } + Ok(()) } } } @@ -305,9 +315,8 @@ pub enum FamilyNameSyntax { 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), + Identifiers, } #[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)] @@ -406,8 +415,6 @@ impl SingleFontFamily { } 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. // The only way this value can be valid with with another keyword. @@ -415,18 +422,23 @@ impl SingleFontFamily { let ident = input.expect_ident()?; value.push(' '); value.push_str(&ident); - serialization.push(' '); - serialize_identifier(&ident, &mut serialization).unwrap(); } while let Ok(ident) = input.try(|i| i.expect_ident_cloned()) { value.push(' '); value.push_str(&ident); - serialization.push(' '); - serialize_identifier(&ident, &mut serialization).unwrap(); } + let syntax = if value.starts_with(' ') || value.ends_with(' ') || value.contains(" ") { + // For font family names which contains special white spaces, e.g. + // `font-family: \ a\ \ b\ \ c\ ;`, it is tricky to serialize them + // as identifiers correctly. Just mark them quoted so we don't need + // to worry about them in serialization code. + FamilyNameSyntax::Quoted + } else { + FamilyNameSyntax::Identifiers + }; Ok(SingleFontFamily::FamilyName(FamilyName { name: Atom::from(value), - syntax: FamilyNameSyntax::Identifiers(serialization), + syntax })) } @@ -461,7 +473,6 @@ impl SingleFontFamily { /// Get the corresponding font-family with family name fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily { use gecko_bindings::structs::FontFamilyType; - use values::serialize_atom_identifier; match family.mType { FontFamilyType::eFamily_sans_serif => SingleFontFamily::Generic(atom!("sans-serif")), @@ -472,11 +483,9 @@ impl SingleFontFamily { FontFamilyType::eFamily_moz_fixed => SingleFontFamily::Generic(Atom::from("-moz-fixed")), FontFamilyType::eFamily_named => { let name = Atom::from(&*family.mName); - let mut serialization = String::new(); - serialize_atom_identifier(&name, &mut serialization).unwrap(); SingleFontFamily::FamilyName(FamilyName { name, - syntax: FamilyNameSyntax::Identifiers(serialization), + syntax: FamilyNameSyntax::Identifiers, }) }, FontFamilyType::eFamily_named_quoted => SingleFontFamily::FamilyName(FamilyName {