mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
style: Record in RestyleHints how far down the tree selector matching must be re-run.
This commit is contained in:
parent
a397590838
commit
178939d8ce
1 changed files with 100 additions and 34 deletions
|
@ -37,11 +37,8 @@ use stylist::SelectorMap;
|
||||||
/// unnecessary.
|
/// unnecessary.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct RestyleHint {
|
pub struct RestyleHint {
|
||||||
/// Rerun selector matching on the element.
|
/// Depths at which selector matching must be re-run.
|
||||||
match_self: bool,
|
match_under_self: RestyleDepths,
|
||||||
|
|
||||||
/// Rerun selector matching on all of the element's descendants.
|
|
||||||
match_descendants: bool,
|
|
||||||
|
|
||||||
/// Rerun selector matching on all later siblings of the element and all
|
/// Rerun selector matching on all later siblings of the element and all
|
||||||
/// of their descendants.
|
/// of their descendants.
|
||||||
|
@ -82,6 +79,75 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Eight bit wide bitfield representing depths of a DOM subtree's descendants,
|
||||||
|
/// used to represent which elements must have selector matching re-run on them.
|
||||||
|
///
|
||||||
|
/// The least significant bit indicates that selector matching must be re-run
|
||||||
|
/// for the element itself, the second least significant bit for the element's
|
||||||
|
/// children, the third its grandchildren, and so on. If the most significant
|
||||||
|
/// bit it set, it indicates that that selector matching must be re-run for
|
||||||
|
/// elements at that depth and all of their descendants.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
struct RestyleDepths(u8);
|
||||||
|
|
||||||
|
impl RestyleDepths {
|
||||||
|
/// Returns a `RestyleDepths` representing no element depths.
|
||||||
|
fn empty() -> Self {
|
||||||
|
RestyleDepths(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `RestyleDepths` representing the current element depth.
|
||||||
|
fn for_self() -> Self {
|
||||||
|
RestyleDepths(0x01)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `RestyleDepths` representing the depths of all descendants of
|
||||||
|
/// the current element.
|
||||||
|
fn for_descendants() -> Self {
|
||||||
|
RestyleDepths(0xfe)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `RestyleDepths` representing the current element depth and the
|
||||||
|
/// depths of all the current element's descendants.
|
||||||
|
fn for_self_and_descendants() -> Self {
|
||||||
|
RestyleDepths(0xff)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this `RestyleDepths` represents the current element
|
||||||
|
/// depth and the depths of all the current element's descendants.
|
||||||
|
fn is_self_and_descendants(&self) -> bool {
|
||||||
|
self.0 == 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this `RestyleDepths` includes any element depth.
|
||||||
|
fn is_any(&self) -> bool {
|
||||||
|
self.0 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this `RestyleDepths` includes the current element depth.
|
||||||
|
fn has_self(&self) -> bool {
|
||||||
|
(self.0 & 0x01) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new `RestyleDepths` with all depth values represented by this
|
||||||
|
/// `RestyleDepths` reduced by one.
|
||||||
|
fn propagate(&self) -> Self {
|
||||||
|
RestyleDepths((self.0 >> 1) | (self.0 & 0x80))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new `RestyleDepths` that represents the union of the depths
|
||||||
|
/// from `self` and `other`.
|
||||||
|
fn insert(&mut self, other: RestyleDepths) {
|
||||||
|
self.0 |= other.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this `RestyleDepths` includes all depths represented
|
||||||
|
/// by `other`.
|
||||||
|
fn contains(&self, other: RestyleDepths) -> bool {
|
||||||
|
(self.0 & other.0) == other.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts that all RestyleReplacements have a matching nsRestyleHint value.
|
/// Asserts that all RestyleReplacements have a matching nsRestyleHint value.
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -116,8 +182,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: false,
|
match_under_self: RestyleDepths::empty(),
|
||||||
match_descendants: false,
|
|
||||||
match_later_siblings: false,
|
match_later_siblings: false,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -128,8 +193,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn for_self() -> Self {
|
pub fn for_self() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: true,
|
match_under_self: RestyleDepths::for_self(),
|
||||||
match_descendants: false,
|
|
||||||
match_later_siblings: false,
|
match_later_siblings: false,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -140,8 +204,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn descendants() -> Self {
|
pub fn descendants() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: false,
|
match_under_self: RestyleDepths::for_descendants(),
|
||||||
match_descendants: true,
|
|
||||||
match_later_siblings: false,
|
match_later_siblings: false,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -152,8 +215,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn later_siblings() -> Self {
|
pub fn later_siblings() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: false,
|
match_under_self: RestyleDepths::empty(),
|
||||||
match_descendants: false,
|
|
||||||
match_later_siblings: true,
|
match_later_siblings: true,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -164,8 +226,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn subtree() -> Self {
|
pub fn subtree() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: true,
|
match_under_self: RestyleDepths::for_self_and_descendants(),
|
||||||
match_descendants: true,
|
|
||||||
match_later_siblings: false,
|
match_later_siblings: false,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -177,8 +238,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn subtree_and_later_siblings() -> Self {
|
pub fn subtree_and_later_siblings() -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: true,
|
match_under_self: RestyleDepths::for_self_and_descendants(),
|
||||||
match_descendants: true,
|
|
||||||
match_later_siblings: true,
|
match_later_siblings: true,
|
||||||
replacements: RestyleReplacements::empty(),
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
|
@ -189,8 +249,7 @@ impl RestyleHint {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn for_replacements(replacements: RestyleReplacements) -> Self {
|
pub fn for_replacements(replacements: RestyleReplacements) -> Self {
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: false,
|
match_under_self: RestyleDepths::empty(),
|
||||||
match_descendants: false,
|
|
||||||
match_later_siblings: false,
|
match_later_siblings: false,
|
||||||
replacements: replacements,
|
replacements: replacements,
|
||||||
}
|
}
|
||||||
|
@ -206,14 +265,16 @@ impl RestyleHint {
|
||||||
/// restyle work, and thus any `insert()` calls will have no effect.
|
/// restyle work, and thus any `insert()` calls will have no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_maximum(&self) -> bool {
|
pub fn is_maximum(&self) -> bool {
|
||||||
self.match_self && self.match_descendants && self.match_later_siblings && self.replacements.is_all()
|
self.match_under_self.is_self_and_descendants() &&
|
||||||
|
self.match_later_siblings &&
|
||||||
|
self.replacements.is_all()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the hint specifies that some work must be performed on
|
/// Returns whether the hint specifies that some work must be performed on
|
||||||
/// the current element.
|
/// the current element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn affects_self(&self) -> bool {
|
pub fn affects_self(&self) -> bool {
|
||||||
self.match_self || !self.replacements.is_empty()
|
self.match_self() || !self.replacements.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the hint specifies that later siblings must be restyled.
|
/// Returns whether the hint specifies that later siblings must be restyled.
|
||||||
|
@ -233,7 +294,7 @@ impl RestyleHint {
|
||||||
/// animation cascade level replacement.
|
/// animation cascade level replacement.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_non_animation_hint(&self) -> bool {
|
pub fn has_non_animation_hint(&self) -> bool {
|
||||||
self.match_self || self.match_descendants || self.match_later_siblings ||
|
self.match_under_self.is_any() || self.match_later_siblings ||
|
||||||
self.replacements.contains(RESTYLE_STYLE_ATTRIBUTE)
|
self.replacements.contains(RESTYLE_STYLE_ATTRIBUTE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,17 +302,17 @@ impl RestyleHint {
|
||||||
/// for the element.
|
/// for the element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn match_self(&self) -> bool {
|
pub fn match_self(&self) -> bool {
|
||||||
self.match_self
|
self.match_under_self.has_self()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `RestyleHint` appropriate for children of the current
|
/// Returns a new `RestyleHint` appropriate for children of the current
|
||||||
/// element.
|
/// element.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn propagate_for_non_animation_restyle(&self) -> Self {
|
pub fn propagate_for_non_animation_restyle(&self) -> Self {
|
||||||
if self.match_descendants {
|
RestyleHint {
|
||||||
Self::subtree()
|
match_under_self: self.match_under_self.propagate(),
|
||||||
} else {
|
match_later_siblings: false,
|
||||||
Self::empty()
|
replacements: RestyleReplacements::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +332,7 @@ impl RestyleHint {
|
||||||
/// Unions the specified `RestyleHint` into this one.
|
/// Unions the specified `RestyleHint` into this one.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert_from(&mut self, other: &Self) {
|
pub fn insert_from(&mut self, other: &Self) {
|
||||||
self.match_self |= other.match_self;
|
self.match_under_self.insert(other.match_under_self);
|
||||||
self.match_descendants |= other.match_descendants;
|
|
||||||
self.match_later_siblings |= other.match_later_siblings;
|
self.match_later_siblings |= other.match_later_siblings;
|
||||||
self.replacements.insert(other.replacements);
|
self.replacements.insert(other.replacements);
|
||||||
}
|
}
|
||||||
|
@ -289,9 +349,8 @@ impl RestyleHint {
|
||||||
/// work as the specified one.
|
/// work as the specified one.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn contains(&mut self, other: &Self) -> bool {
|
pub fn contains(&mut self, other: &Self) -> bool {
|
||||||
!(other.match_self && !self.match_self) &&
|
self.match_under_self.contains(other.match_under_self) &&
|
||||||
!(other.match_descendants && !self.match_descendants) &&
|
(self.match_later_siblings & other.match_later_siblings) == other.match_later_siblings &&
|
||||||
!(other.match_later_siblings && !self.match_later_siblings) &&
|
|
||||||
self.replacements.contains(other.replacements)
|
self.replacements.contains(other.replacements)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,9 +378,16 @@ impl From<nsRestyleHint> for RestyleHint {
|
||||||
use gecko_bindings::structs::nsRestyleHint_eRestyle_SomeDescendants as eRestyle_SomeDescendants;
|
use gecko_bindings::structs::nsRestyleHint_eRestyle_SomeDescendants as eRestyle_SomeDescendants;
|
||||||
use gecko_bindings::structs::nsRestyleHint_eRestyle_Subtree as eRestyle_Subtree;
|
use gecko_bindings::structs::nsRestyleHint_eRestyle_Subtree as eRestyle_Subtree;
|
||||||
|
|
||||||
|
let mut match_under_self = RestyleDepths::empty();
|
||||||
|
if (raw.0 & (eRestyle_Self.0 | eRestyle_Subtree.0)) != 0 {
|
||||||
|
match_under_self.insert(RestyleDepths::for_self());
|
||||||
|
}
|
||||||
|
if (raw.0 & (eRestyle_Subtree.0 | eRestyle_SomeDescendants.0)) != 0 {
|
||||||
|
match_under_self.insert(RestyleDepths::for_descendants());
|
||||||
|
}
|
||||||
|
|
||||||
RestyleHint {
|
RestyleHint {
|
||||||
match_self: (raw.0 & (eRestyle_Self.0 | eRestyle_Subtree.0)) != 0,
|
match_under_self: match_under_self,
|
||||||
match_descendants: (raw.0 & (eRestyle_Subtree.0 | eRestyle_SomeDescendants.0)) != 0,
|
|
||||||
match_later_siblings: (raw.0 & eRestyle_LaterSiblings.0) != 0,
|
match_later_siblings: (raw.0 & eRestyle_LaterSiblings.0) != 0,
|
||||||
replacements: raw.into(),
|
replacements: raw.into(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue