--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -9,16 +9,17 @@ use app_units::Au;
use byteorder::{BigEndian, ByteOrder};
use cssparser::{CssStringWriter, Parser, serialize_identifier};
#[cfg(feature = "gecko")]
use gecko_bindings::{bindings, structs};
#[cfg(feature = "gecko")]
use gecko_bindings::sugar::refptr::RefPtr;
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
+use std::borrow::Cow;
use std::fmt::{self, Write};
#[cfg(feature = "gecko")]
use std::hash::{Hash, Hasher};
#[cfg(feature = "servo")]
use std::slice;
use style_traits::{CssWriter, ParseError, ToCss};
use values::CSSFloat;
use values::animated::{ToAnimatedValue, ToAnimatedZero};
@@ -281,38 +282,35 @@ pub struct FamilyName {
impl ToCss for FamilyName {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
match self.syntax {
FamilyNameSyntax::Quoted => {
dest.write_char('"')?;
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::Identifier => {
+ serialize_identifier(&self.name.to_string(), dest)
}
}
}
}
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// Font family names must either be given quoted as strings,
/// or unquoted as a sequence of one or more identifiers.
pub enum FamilyNameSyntax {
/// The family name was specified in a quoted form, e.g. "Font Name"
- /// or 'Font Name'.
+ /// or 'Font Name', or as a list of unquoted identifiers.
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),
+ /// The family name was specified in an unquoted form as a single
+ /// identifier.
+ Identifier,
}
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// A set of faces that vary in weight, width or slope.
pub enum SingleFontFamily {
/// The name of a font family of choice.
FamilyName(FamilyName),
@@ -400,38 +398,42 @@ impl SingleFontFamily {
// 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.as_ref().to_owned();
- let mut serialization = String::new();
- serialize_identifier(&first_ident, &mut serialization).unwrap();
+ let mut syntax = FamilyNameSyntax::Identifier;
+ let mut value = Cow::Borrowed(first_ident.as_ref());
// These keywords are not allowed by themselves.
// The only way this value can be valid with with another keyword.
if css_wide_keyword {
+ syntax = FamilyNameSyntax::Quoted;
+
let ident = input.expect_ident()?;
+
+ let value = value.to_mut();
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()) {
+ syntax = FamilyNameSyntax::Quoted;
+
+ let value = value.to_mut();
value.push(' ');
value.push_str(&ident);
- serialization.push(' ');
- serialize_identifier(&ident, &mut serialization).unwrap();
}
+
Ok(SingleFontFamily::FamilyName(FamilyName {
name: Atom::from(value),
- syntax: FamilyNameSyntax::Identifiers(serialization),
+ syntax,
}))
}
#[cfg(feature = "gecko")]
/// Return the generic ID for a given generic font name
pub fn generic(name: &Atom) -> (structs::FontFamilyType, u8) {
use gecko_bindings::structs::FontFamilyType;
if *name == atom!("serif") {
@@ -466,21 +468,19 @@ impl SingleFontFamily {
FontFamilyType::eFamily_sans_serif => SingleFontFamily::Generic(atom!("sans-serif")),
FontFamilyType::eFamily_serif => SingleFontFamily::Generic(atom!("serif")),
FontFamilyType::eFamily_monospace => SingleFontFamily::Generic(atom!("monospace")),
FontFamilyType::eFamily_cursive => SingleFontFamily::Generic(atom!("cursive")),
FontFamilyType::eFamily_fantasy => SingleFontFamily::Generic(atom!("fantasy")),
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_identifier(&name.to_string(), &mut serialization).unwrap();
SingleFontFamily::FamilyName(FamilyName {
name: name.clone(),
- syntax: FamilyNameSyntax::Identifiers(serialization),
+ syntax: FamilyNameSyntax::Identifier,
})
},
FontFamilyType::eFamily_named_quoted => SingleFontFamily::FamilyName(FamilyName {
name: (&*family.mName).into(),
syntax: FamilyNameSyntax::Quoted,
}),
_ => panic!("Found unexpected font FontFamilyType"),
}
@@ -616,17 +616,17 @@ impl FontFamilyList {
}
None
}
}
#[cfg(feature = "gecko")]
/// Iterator of FontFamily
pub struct FontFamilyNameIter<'a> {
- names: &'a structs::nsTArray<structs::FontFamilyName>,
+ names: &'a [structs::FontFamilyName],
cur: usize,
}
#[cfg(feature = "gecko")]
impl<'a> Iterator for FontFamilyNameIter<'a> {
type Item = SingleFontFamily;
fn next(&mut self) -> Option<Self::Item> {