diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index d51a43166b9..b79f08cb500 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -4187,9 +4187,9 @@ fn static_assert() { UniqueRefPtr::from_addrefed(Gecko_NewStyleQuoteValues(other.0.len() as u32)) }; - for (servo, gecko) in other.0.into_iter().zip(refptr.mQuotePairs.iter_mut()) { - gecko.first.assign_str(&servo.0); - gecko.second.assign_str(&servo.1); + for (servo, gecko) in other.0.iter().zip(refptr.mQuotePairs.iter_mut()) { + gecko.first.assign_str(&servo.opening); + gecko.second.assign_str(&servo.closing); } self.gecko.mQuotes.set_move(refptr.get()) @@ -4206,14 +4206,14 @@ fn static_assert() { pub fn clone_quotes(&self) -> longhands::quotes::computed_value::T { unsafe { let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr; - longhands::quotes::computed_value::T( + longhands::quotes::computed_value::T(Arc::new( gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| { - ( - gecko_pair.first.to_string().into_boxed_str(), - gecko_pair.second.to_string().into_boxed_str(), - ) + values::specified::QuotePair { + opening: gecko_pair.first.to_string().into_boxed_str(), + closing: gecko_pair.second.to_string().into_boxed_str(), + } }).collect::>().into_boxed_slice() - ) + )) } } diff --git a/components/style/values/computed/list.rs b/components/style/values/computed/list.rs index bd3930fa8de..d7a69a18e99 100644 --- a/components/style/values/computed/list.rs +++ b/components/style/values/computed/list.rs @@ -6,26 +6,30 @@ #[cfg(feature = "gecko")] pub use values::specified::list::ListStyleType; -pub use values::specified::list::Quotes; +pub use values::specified::list::{QuotePair, Quotes}; + +use servo_arc::Arc; +use values::specified::list::QuotePair; + +lazy_static! { + static ref INITIAL_QUOTES: Arc> = Arc::new( + vec![ + QuotePair { + opening: "\u{201c}".to_owned().into_boxed_str(), + closing: "\u{201d}".to_owned().into_boxed_str(), + }, + QuotePair { + opening: "\u{2018}".to_owned().into_boxed_str(), + closing: "\u{2019}".to_owned().into_boxed_str(), + }, + ].into_boxed_slice() + ); +} impl Quotes { /// Initial value for `quotes`. - /// - /// FIXME(emilio): This should ideally not allocate. #[inline] pub fn get_initial_value() -> Quotes { - Quotes( - vec![ - ( - "\u{201c}".to_owned().into_boxed_str(), - "\u{201d}".to_owned().into_boxed_str(), - ), - ( - "\u{2018}".to_owned().into_boxed_str(), - "\u{2019}".to_owned().into_boxed_str(), - ), - ] - .into_boxed_slice(), - ) + Quotes(INITIAL_QUOTES.clone()) } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index a5c83eb43e0..9039f2033f6 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -69,7 +69,7 @@ pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLe pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto}; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; -pub use self::list::Quotes; +pub use self::list::{QuotePair, Quotes}; pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::percentage::{NonNegativePercentage, Percentage}; diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index 4e30364eff5..c4aebb289fe 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -6,8 +6,8 @@ use cssparser::{Parser, Token}; use parser::{Parse, ParserContext}; -use std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use servo_arc::Arc; +use style_traits::{ParseError, StyleParseErrorKind}; #[cfg(feature = "gecko")] use values::generics::CounterStyleOrNone; #[cfg(feature = "gecko")] @@ -73,41 +73,25 @@ impl Parse for ListStyleType { } } -/// Specified and computed `quote` property. -/// -/// FIXME(emilio): It's a shame that this allocates all the time it's computed, -/// probably should just be refcounted. -/// FIXME This can probably derive ToCss. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] -pub struct Quotes(#[css(if_empty = "none")] pub Box<[(Box, Box)]>); +/// A quote pair. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +pub struct QuotePair { + /// The opening quote. + pub opening: Box, -impl ToCss for Quotes { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - let mut iter = self.0.iter(); - - match iter.next() { - Some(&(ref l, ref r)) => { - l.to_css(dest)?; - dest.write_char(' ')?; - r.to_css(dest)?; - }, - None => return dest.write_str("none"), - } - - for &(ref l, ref r) in iter { - dest.write_char(' ')?; - l.to_css(dest)?; - dest.write_char(' ')?; - r.to_css(dest)?; - } - - Ok(()) - } + /// The closing quote. + pub closing: Box, } +/// Specified and computed `quotes` property. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +pub struct Quotes( + #[css(if_empty = "none")] + #[css(iterable)] + #[ignore_malloc_size_of = "Arc"] + pub Arc> +); + impl Parse for Quotes { fn parse<'i, 't>( _: &ParserContext, @@ -117,24 +101,24 @@ impl Parse for Quotes { .try(|input| input.expect_ident_matching("none")) .is_ok() { - return Ok(Quotes(Vec::new().into_boxed_slice())); + return Ok(Quotes(Arc::new(Box::new([])))); } let mut quotes = Vec::new(); loop { let location = input.current_source_location(); - let first = match input.next() { + let opening = match input.next() { Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into_boxed_str(), Ok(t) => return Err(location.new_unexpected_token_error(t.clone())), Err(_) => break, }; - let second = input.expect_string()?.as_ref().to_owned().into_boxed_str(); - quotes.push((first, second)) + let closing = input.expect_string()?.as_ref().to_owned().into_boxed_str(); + quotes.push(QuotePair { opening, closing }); } if !quotes.is_empty() { - Ok(Quotes(quotes.into_boxed_slice())) + Ok(Quotes(Arc::new(quotes.into_boxed_slice()))) } else { Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index afac1f50a39..d96094488f6 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -63,7 +63,7 @@ pub use self::length::{NoCalcLength, ViewportPercentageLength}; pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto}; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; -pub use self::list::Quotes; +pub use self::list::{QuotePair, Quotes}; pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::percentage::Percentage;