From be2f70393f858f8b4f3eccca0925cecb3d8ba47b Mon Sep 17 00:00:00 2001 From: David Raifaizen Date: Sat, 2 Apr 2016 12:20:25 -0400 Subject: [PATCH] Adding more efficient way of determining if PropertyDeclaration is important --- .../style/properties/properties.mako.rs | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index c81be955540..301e9a3026b 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -254,9 +254,10 @@ mod property_bit_field { % endif % endfor -/// Declarations are stored in reverse order. -/// Overridden declarations are skipped. +use std::iter::{Iterator, Chain, Zip, Rev, Repeat, repeat}; +use std::slice; +/// Overridden declarations are skipped. // FIXME (https://github.com/servo/servo/issues/3426) #[derive(Debug, PartialEq, HeapSizeOf)] @@ -267,6 +268,19 @@ pub struct PropertyDeclarationBlock { pub normal: Arc>, } +impl PropertyDeclarationBlock { + /// Provides an iterator of all declarations, with indication of !important value + pub fn declarations(&self) -> Chain< + Zip>, Repeat>, + Zip>, Repeat> + > { + // Declarations are stored in reverse order. + let normal = self.normal.iter().rev().zip(repeat(false)); + let important = self.important.iter().rev().zip(repeat(true)); + normal.chain(important) + } +} + impl ToCss for PropertyDeclarationBlock { // https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -278,8 +292,7 @@ impl ToCss for PropertyDeclarationBlock { let mut already_serialized = Vec::new(); // Step 3 - // restore order of declarations since PropertyDeclarationBlock is stored in reverse order - for declaration in self.important.iter().chain(self.normal.iter()).rev() { + for (declaration, important) in self.declarations() { // Step 3.1 let property = declaration.name(); @@ -293,8 +306,8 @@ impl ToCss for PropertyDeclarationBlock { if !shorthands.is_empty() { // Step 3.3.1 - let mut longhands = self.important.iter().chain(self.normal.iter()).rev() - .filter(|d| !already_serialized.contains(&d.name())) + let mut longhands = self.declarations() + .filter(|d| !already_serialized.contains(&d.0.name())) .collect::>(); // Step 3.3.2 @@ -303,24 +316,27 @@ impl ToCss for PropertyDeclarationBlock { // Substep 2 & 3 let mut current_longhands = Vec::new(); + let mut important_count = 0; for longhand in longhands.iter() { - let longhand_name = longhand.name(); + let longhand_name = longhand.0.name(); if properties.iter().any(|p| &longhand_name == *p) { - current_longhands.push(*longhand); + current_longhands.push(longhand.0); + if longhand.1 == true { + important_count += 1; + } } } // Substep 1 + /* Assuming that the PropertyDeclarationBlock contains no duplicate entries, + if the current_longhands length is equal to the properties length, it means + that the properties that map to shorthand are present in longhands */ if current_longhands.is_empty() || current_longhands.len() != properties.len() { continue; } // Substep 4 - let important_count = current_longhands.iter() - .filter(|l| self.important.contains(l)) - .count(); - let is_important = important_count > 0; if is_important && important_count != current_longhands.len() { continue; @@ -340,7 +356,7 @@ impl ToCss for PropertyDeclarationBlock { for current_longhand in current_longhands { // Substep 9 already_serialized.push(current_longhand.name()); - let index_to_remove = longhands.iter().position(|l| l == ¤t_longhand); + let index_to_remove = longhands.iter().position(|l| l.0 == current_longhand); if let Some(index) = index_to_remove { // Substep 10 longhands.remove(index); @@ -355,11 +371,10 @@ impl ToCss for PropertyDeclarationBlock { } // Steps 3.3.5, 3.3.6 & 3.3.7 - let append_important = self.important.contains(declaration); try!(append_serialization(dest, &property.to_string(), AppendableValue::Declaration(declaration), - append_important, + important, &mut is_first_serialization)); // Step 3.3.8 @@ -380,7 +395,7 @@ fn append_serialization(dest: &mut W, property_name: &str, appendable_value: AppendableValue, is_important: bool, - is_first_serialization: &mut bool) -> fmt::Result where W: fmt::Write + is_first_serialization: &mut bool) -> fmt::Result where W: fmt::Write { // after first serialization(key: value;) add whitespace between the pairs if !*is_first_serialization {