mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
Rewrite deduplicate_property_declarations to not require Mako.
This commit is contained in:
parent
6318c4b699
commit
066c5a01b2
1 changed files with 77 additions and 74 deletions
|
@ -178,47 +178,49 @@ pub mod animated_properties {
|
||||||
<%include file="/helpers/animated_properties.mako.rs" />
|
<%include file="/helpers/animated_properties.mako.rs" />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO(SimonSapin): Convert this to a syntax extension rather than a Mako template.
|
|
||||||
// Maybe submit for inclusion in libstd?
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub mod property_bit_field {
|
pub mod property_bit_field {
|
||||||
use logical_geometry::WritingMode;
|
use logical_geometry::WritingMode;
|
||||||
use properties::animated_properties::TransitionProperty;
|
use properties::animated_properties::TransitionProperty;
|
||||||
|
use properties::LonghandId;
|
||||||
|
|
||||||
/// A bitfield for all longhand properties, in order to quickly test whether
|
/// A set of longhand properties
|
||||||
/// we've seen one of them.
|
|
||||||
pub struct PropertyBitField {
|
pub struct PropertyBitField {
|
||||||
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
|
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PropertyBitField {
|
impl PropertyBitField {
|
||||||
/// Create a new `PropertyBitField`, with all the bits set to zero.
|
/// Create an empty set
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> PropertyBitField {
|
pub fn new() -> PropertyBitField {
|
||||||
PropertyBitField { storage: [0; (${len(data.longhands)} - 1 + 32) / 32] }
|
PropertyBitField { storage: [0; (${len(data.longhands)} - 1 + 32) / 32] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return whether the given property is in the set
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, bit: usize) -> bool {
|
pub fn contains(&self, id: LonghandId) -> bool {
|
||||||
|
let bit = id as usize;
|
||||||
(self.storage[bit / 32] & (1 << (bit % 32))) != 0
|
(self.storage[bit / 32] & (1 << (bit % 32))) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the given property to the set
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set(&mut self, bit: usize) {
|
pub fn insert(&mut self, id: LonghandId) {
|
||||||
self.storage[bit / 32] |= 1 << (bit % 32)
|
let bit = id as usize;
|
||||||
|
self.storage[bit / 32] |= 1 << (bit % 32);
|
||||||
}
|
}
|
||||||
% for i, property in enumerate(data.longhands):
|
|
||||||
|
% for property in data.longhands:
|
||||||
% if not property.derived_from:
|
% if not property.derived_from:
|
||||||
#[allow(non_snake_case, missing_docs)]
|
#[allow(non_snake_case, missing_docs)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_${property.ident}(&self) -> bool {
|
pub fn get_${property.ident}(&self) -> bool {
|
||||||
self.get(${i})
|
self.contains(LonghandId::${property.camel_case})
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case, missing_docs)]
|
#[allow(non_snake_case, missing_docs)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_${property.ident}(&mut self) {
|
pub fn set_${property.ident}(&mut self) {
|
||||||
self.set(${i})
|
self.insert(LonghandId::${property.camel_case})
|
||||||
}
|
}
|
||||||
% endif
|
% endif
|
||||||
% if property.logical:
|
% if property.logical:
|
||||||
|
@ -245,9 +247,9 @@ pub mod property_bit_field {
|
||||||
/// This function will panic if TransitionProperty::All is given.
|
/// This function will panic if TransitionProperty::All is given.
|
||||||
pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) {
|
pub fn set_transition_property_bit(&mut self, property: &TransitionProperty) {
|
||||||
match *property {
|
match *property {
|
||||||
% for i, prop in enumerate(data.longhands):
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
TransitionProperty::${prop.camel_case} => self.set(${i}),
|
TransitionProperty::${prop.camel_case} => self.insert(LonghandId::${prop.camel_case}),
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
TransitionProperty::All => unreachable!("Tried to set TransitionProperty::All in a PropertyBitfield"),
|
TransitionProperty::All => unreachable!("Tried to set TransitionProperty::All in a PropertyBitfield"),
|
||||||
|
@ -258,9 +260,9 @@ pub mod property_bit_field {
|
||||||
/// This function will panic if TransitionProperty::All is given.
|
/// This function will panic if TransitionProperty::All is given.
|
||||||
pub fn has_transition_property_bit(&self, property: &TransitionProperty) -> bool {
|
pub fn has_transition_property_bit(&self, property: &TransitionProperty) -> bool {
|
||||||
match *property {
|
match *property {
|
||||||
% for i, prop in enumerate(data.longhands):
|
% for prop in data.longhands:
|
||||||
% if prop.animatable:
|
% if prop.animatable:
|
||||||
TransitionProperty::${prop.camel_case} => self.get(${i}),
|
TransitionProperty::${prop.camel_case} => self.contains(LonghandId::${prop.camel_case}),
|
||||||
% endif
|
% endif
|
||||||
% endfor
|
% endfor
|
||||||
TransitionProperty::All => unreachable!("Tried to get TransitionProperty::All in a PropertyBitfield"),
|
TransitionProperty::All => unreachable!("Tried to get TransitionProperty::All in a PropertyBitfield"),
|
||||||
|
@ -269,6 +271,44 @@ pub mod property_bit_field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A specialized set of PropertyDeclarationId
|
||||||
|
pub struct PropertyDeclarationIdSet {
|
||||||
|
longhands: PropertyBitField,
|
||||||
|
|
||||||
|
// FIXME: Use a HashSet instead? This Vec is usually small, so linear scan might be ok.
|
||||||
|
custom: Vec<::custom_properties::Name>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropertyDeclarationIdSet {
|
||||||
|
/// Empty set
|
||||||
|
pub fn new() -> Self {
|
||||||
|
PropertyDeclarationIdSet {
|
||||||
|
longhands: PropertyBitField::new(),
|
||||||
|
custom: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether the given ID is in the set
|
||||||
|
pub fn contains(&mut self, id: PropertyDeclarationId) -> bool {
|
||||||
|
match id {
|
||||||
|
PropertyDeclarationId::Longhand(id) => self.longhands.contains(id),
|
||||||
|
PropertyDeclarationId::Custom(name) => self.custom.contains(name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert the given ID in the set
|
||||||
|
pub fn insert(&mut self, id: PropertyDeclarationId) {
|
||||||
|
match id {
|
||||||
|
PropertyDeclarationId::Longhand(id) => self.longhands.insert(id),
|
||||||
|
PropertyDeclarationId::Custom(name) => {
|
||||||
|
if !self.custom.contains(name) {
|
||||||
|
self.custom.push(name.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
% for property in data.longhands:
|
% for property in data.longhands:
|
||||||
% if not property.derived_from:
|
% if not property.derived_from:
|
||||||
/// Perform CSS variable substitution if needed, and execute `f` with
|
/// Perform CSS variable substitution if needed, and execute `f` with
|
||||||
|
@ -373,59 +413,29 @@ pub mod property_bit_field {
|
||||||
/// The input and output are in source order
|
/// The input and output are in source order
|
||||||
fn deduplicate_property_declarations(block: &mut PropertyDeclarationBlock) {
|
fn deduplicate_property_declarations(block: &mut PropertyDeclarationBlock) {
|
||||||
let mut deduplicated = Vec::with_capacity(block.declarations.len());
|
let mut deduplicated = Vec::with_capacity(block.declarations.len());
|
||||||
let mut seen_normal = PropertyBitField::new();
|
let mut seen_normal = PropertyDeclarationIdSet::new();
|
||||||
let mut seen_important = PropertyBitField::new();
|
let mut seen_important = PropertyDeclarationIdSet::new();
|
||||||
let mut seen_custom_normal = Vec::new();
|
|
||||||
let mut seen_custom_important = Vec::new();
|
|
||||||
|
|
||||||
for (declaration, importance) in block.declarations.drain(..).rev() {
|
for (declaration, importance) in block.declarations.drain(..).rev() {
|
||||||
match declaration {
|
if importance.important() {
|
||||||
% for property in data.longhands:
|
let id = declaration.id();
|
||||||
PropertyDeclaration::${property.camel_case}(..) => {
|
if seen_important.contains(id) {
|
||||||
% if not property.derived_from:
|
block.important_count -= 1;
|
||||||
if importance.important() {
|
continue
|
||||||
if seen_important.get_${property.ident}() {
|
|
||||||
block.important_count -= 1;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if seen_normal.get_${property.ident}() {
|
|
||||||
remove_one(&mut deduplicated, |d| {
|
|
||||||
matches!(d, &(PropertyDeclaration::${property.camel_case}(..), _))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
seen_important.set_${property.ident}()
|
|
||||||
} else {
|
|
||||||
if seen_normal.get_${property.ident}() ||
|
|
||||||
seen_important.get_${property.ident}() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
seen_normal.set_${property.ident}()
|
|
||||||
}
|
|
||||||
% else:
|
|
||||||
unreachable!();
|
|
||||||
% endif
|
|
||||||
},
|
|
||||||
% endfor
|
|
||||||
PropertyDeclaration::Custom(ref name, _) => {
|
|
||||||
if importance.important() {
|
|
||||||
if seen_custom_important.contains(name) {
|
|
||||||
block.important_count -= 1;
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if seen_custom_normal.contains(name) {
|
|
||||||
remove_one(&mut deduplicated, |d| {
|
|
||||||
matches!(d, &(PropertyDeclaration::Custom(ref n, _), _) if n == name)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
seen_custom_important.push(name.clone())
|
|
||||||
} else {
|
|
||||||
if seen_custom_normal.contains(name) ||
|
|
||||||
seen_custom_important.contains(name) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
seen_custom_normal.push(name.clone())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if seen_normal.contains(id) {
|
||||||
|
let previous_len = deduplicated.len();
|
||||||
|
deduplicated.retain(|&(ref d, _)| PropertyDeclaration::id(d) != id);
|
||||||
|
debug_assert_eq!(deduplicated.len(), previous_len - 1);
|
||||||
|
}
|
||||||
|
seen_important.insert(id);
|
||||||
|
} else {
|
||||||
|
let id = declaration.id();
|
||||||
|
if seen_normal.contains(id) ||
|
||||||
|
seen_important.contains(id) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen_normal.insert(id)
|
||||||
}
|
}
|
||||||
deduplicated.push((declaration, importance))
|
deduplicated.push((declaration, importance))
|
||||||
}
|
}
|
||||||
|
@ -433,13 +443,6 @@ fn deduplicate_property_declarations(block: &mut PropertyDeclarationBlock) {
|
||||||
block.declarations = deduplicated;
|
block.declarations = deduplicated;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn remove_one<T, F: FnMut(&T) -> bool>(v: &mut Vec<T>, mut remove_this: F) {
|
|
||||||
let previous_len = v.len();
|
|
||||||
v.retain(|x| !remove_this(x));
|
|
||||||
debug_assert_eq!(v.len(), previous_len - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An enum to represent a CSS Wide keyword.
|
/// An enum to represent a CSS Wide keyword.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum CSSWideKeyword {
|
pub enum CSSWideKeyword {
|
||||||
|
@ -653,7 +656,7 @@ impl<T: ToCss> ToCss for DeclaredValue<T> {
|
||||||
|
|
||||||
/// An identifier for a given property declaration, which can be either a
|
/// An identifier for a given property declaration, which can be either a
|
||||||
/// longhand or a custom property.
|
/// longhand or a custom property.
|
||||||
#[derive(PartialEq, Clone)]
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||||
pub enum PropertyDeclarationId<'a> {
|
pub enum PropertyDeclarationId<'a> {
|
||||||
/// A longhand.
|
/// A longhand.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue