mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Define a CascadeLevel enum, and make the rule tree operate on it.
We'll use this level to know where to stop replacing nodes in the tree.
This commit is contained in:
parent
31ecc9b692
commit
314f2ce714
6 changed files with 144 additions and 64 deletions
|
@ -151,11 +151,11 @@ impl RuleTree {
|
|||
/// Insert the given rules, that must be in proper order by specifity, and
|
||||
/// return the corresponding rule node representing the last inserted one.
|
||||
pub fn insert_ordered_rules<'a, I>(&self, iter: I) -> StrongRuleNode
|
||||
where I: Iterator<Item=(StyleSource, Importance)>,
|
||||
where I: Iterator<Item=(StyleSource, CascadeLevel)>,
|
||||
{
|
||||
let mut current = self.root.clone();
|
||||
for (source, importance) in iter {
|
||||
current = current.ensure_child(self.root.downgrade(), source, importance);
|
||||
for (source, level) in iter {
|
||||
current = current.ensure_child(self.root.downgrade(), source, level);
|
||||
}
|
||||
current
|
||||
}
|
||||
|
@ -176,6 +176,66 @@ impl RuleTree {
|
|||
/// where it likely did not result from a rigorous performance analysis.)
|
||||
const RULE_TREE_GC_INTERVAL: usize = 300;
|
||||
|
||||
/// The cascade level these rules are relevant at, as per[1].
|
||||
///
|
||||
/// The order of variants declared here is significant, and must be in
|
||||
/// _ascending_ order of precedence.
|
||||
///
|
||||
/// [1]: https://drafts.csswg.org/css-cascade/#cascade-origin
|
||||
#[repr(u8)]
|
||||
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum CascadeLevel {
|
||||
/// Normal User-Agent rules.
|
||||
UANormal = 0,
|
||||
/// Presentational hints.
|
||||
PresHints,
|
||||
/// User normal rules.
|
||||
UserNormal,
|
||||
/// Author normal rules.
|
||||
AuthorNormal,
|
||||
/// Style attribute normal rules.
|
||||
StyleAttributeNormal,
|
||||
/// CSS animations and script-generated animations.
|
||||
Animations,
|
||||
/// Author-supplied important rules.
|
||||
AuthorImportant,
|
||||
/// Style attribute important rules.
|
||||
StyleAttributeImportant,
|
||||
/// User important rules.
|
||||
UserImportant,
|
||||
/// User-agent important rules.
|
||||
UAImportant,
|
||||
/// Transitions
|
||||
Transitions,
|
||||
}
|
||||
|
||||
impl CascadeLevel {
|
||||
/// Returns whether this cascade level represents important rules of some
|
||||
/// sort.
|
||||
#[inline]
|
||||
pub fn is_important(&self) -> bool {
|
||||
match *self {
|
||||
CascadeLevel::AuthorImportant |
|
||||
CascadeLevel::StyleAttributeImportant |
|
||||
CascadeLevel::UserImportant |
|
||||
CascadeLevel::UAImportant => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the importance relevant for this rule. Pretty similar to
|
||||
/// `is_important`.
|
||||
#[inline]
|
||||
pub fn importance(&self) -> Importance {
|
||||
if self.is_important() {
|
||||
Importance::Important
|
||||
} else {
|
||||
Importance::Normal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RuleNode {
|
||||
/// The root node. Only the root has no root pointer, for obvious reasons.
|
||||
root: Option<WeakRuleNode>,
|
||||
|
@ -187,9 +247,8 @@ struct RuleNode {
|
|||
/// or a raw property declaration block (like the style attribute).
|
||||
source: Option<StyleSource>,
|
||||
|
||||
/// The importance of the declarations relevant in the style rule,
|
||||
/// meaningless in the root node.
|
||||
importance: Importance,
|
||||
/// The cascade level this rule is positioned at.
|
||||
cascade_level: CascadeLevel,
|
||||
|
||||
refcount: AtomicUsize,
|
||||
first_child: AtomicPtr<RuleNode>,
|
||||
|
@ -215,13 +274,13 @@ impl RuleNode {
|
|||
fn new(root: WeakRuleNode,
|
||||
parent: StrongRuleNode,
|
||||
source: StyleSource,
|
||||
importance: Importance) -> Self {
|
||||
cascade_level: CascadeLevel) -> Self {
|
||||
debug_assert!(root.upgrade().parent().is_none());
|
||||
RuleNode {
|
||||
root: Some(root),
|
||||
parent: Some(parent),
|
||||
source: Some(source),
|
||||
importance: importance,
|
||||
cascade_level: cascade_level,
|
||||
refcount: AtomicUsize::new(1),
|
||||
first_child: AtomicPtr::new(ptr::null_mut()),
|
||||
next_sibling: AtomicPtr::new(ptr::null_mut()),
|
||||
|
@ -236,7 +295,7 @@ impl RuleNode {
|
|||
root: None,
|
||||
parent: None,
|
||||
source: None,
|
||||
importance: Importance::Normal,
|
||||
cascade_level: CascadeLevel::UANormal,
|
||||
refcount: AtomicUsize::new(1),
|
||||
first_child: AtomicPtr::new(ptr::null_mut()),
|
||||
next_sibling: AtomicPtr::new(ptr::null_mut()),
|
||||
|
@ -385,10 +444,10 @@ impl StrongRuleNode {
|
|||
fn ensure_child(&self,
|
||||
root: WeakRuleNode,
|
||||
source: StyleSource,
|
||||
importance: Importance) -> StrongRuleNode {
|
||||
cascade_level: CascadeLevel) -> StrongRuleNode {
|
||||
let mut last = None;
|
||||
for child in self.get().iter_children() {
|
||||
if child .get().importance == importance &&
|
||||
if child .get().cascade_level == cascade_level &&
|
||||
child.get().source.as_ref().unwrap().ptr_equals(&source) {
|
||||
return child;
|
||||
}
|
||||
|
@ -398,7 +457,7 @@ impl StrongRuleNode {
|
|||
let mut node = Box::new(RuleNode::new(root,
|
||||
self.clone(),
|
||||
source.clone(),
|
||||
importance));
|
||||
cascade_level));
|
||||
let new_ptr: *mut RuleNode = &mut *node;
|
||||
|
||||
loop {
|
||||
|
@ -462,7 +521,7 @@ impl StrongRuleNode {
|
|||
|
||||
/// Get the importance that this rule node represents.
|
||||
pub fn importance(&self) -> Importance {
|
||||
self.get().importance
|
||||
self.get().cascade_level.importance()
|
||||
}
|
||||
|
||||
/// Get an iterator for this rule node and its ancestors.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue