mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Handle importance when inserting into the rule tree.
This commit is contained in:
parent
48b5e5ebc4
commit
e9d4110ad4
4 changed files with 141 additions and 143 deletions
|
@ -10,6 +10,7 @@
|
|||
use heapsize::HeapSizeOf;
|
||||
use properties::{Importance, PropertyDeclarationBlock};
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
use smallvec::SmallVec;
|
||||
use std::io::{self, Write};
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||
|
@ -124,6 +125,96 @@ impl RuleTree {
|
|||
self.dump(guards, &mut stdout);
|
||||
}
|
||||
|
||||
/// Inserts the given rules, that must be in proper order by specifity, and
|
||||
/// returns the corresponding rule node representing the last inserted one.
|
||||
///
|
||||
/// !important rules are detected and inserted into the appropriate position
|
||||
/// in the rule tree. This allows selector matching to ignore importance,
|
||||
/// while still maintaining the appropriate cascade order in the rule tree.
|
||||
pub fn insert_ordered_rules_with_important<'a, I>(&self,
|
||||
iter: I,
|
||||
guards: &StylesheetGuards)
|
||||
-> StrongRuleNode
|
||||
where I: Iterator<Item=(StyleSource, CascadeLevel)>,
|
||||
{
|
||||
use self::CascadeLevel::*;
|
||||
let mut current = self.root.clone();
|
||||
let mut last_level = current.get().level;
|
||||
|
||||
let mut found_important = false;
|
||||
let mut important_style_attr = None;
|
||||
let mut important_author = SmallVec::<[StyleSource; 4]>::new();
|
||||
let mut important_user = SmallVec::<[StyleSource; 4]>::new();
|
||||
let mut important_ua = SmallVec::<[StyleSource; 4]>::new();
|
||||
let mut transition = None;
|
||||
|
||||
for (source, level) in iter {
|
||||
debug_assert!(last_level <= level, "Not really ordered");
|
||||
debug_assert!(!level.is_important(), "Important levels handled internally");
|
||||
let (any_normal, any_important) = {
|
||||
let pdb = source.read(level.guard(guards));
|
||||
(pdb.any_normal(), pdb.any_important())
|
||||
};
|
||||
if any_important {
|
||||
found_important = true;
|
||||
match level {
|
||||
AuthorNormal => important_author.push(source.clone()),
|
||||
UANormal => important_ua.push(source.clone()),
|
||||
UserNormal => important_user.push(source.clone()),
|
||||
StyleAttributeNormal => {
|
||||
debug_assert!(important_style_attr.is_none());
|
||||
important_style_attr = Some(source.clone());
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
}
|
||||
if any_normal {
|
||||
if matches!(level, Transitions) && found_important {
|
||||
// There can be at most one transition, and it will come at
|
||||
// the end of the iterator. Stash it and apply it after
|
||||
// !important rules.
|
||||
debug_assert!(transition.is_none());
|
||||
transition = Some(source);
|
||||
} else {
|
||||
current = current.ensure_child(self.root.downgrade(), source, level);
|
||||
}
|
||||
}
|
||||
last_level = level;
|
||||
}
|
||||
|
||||
// Early-return in the common case of no !important declarations.
|
||||
if !found_important {
|
||||
return current;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert important declarations, in order of increasing importance,
|
||||
// followed by any transition rule.
|
||||
//
|
||||
|
||||
for source in important_author.into_iter() {
|
||||
current = current.ensure_child(self.root.downgrade(), source, AuthorImportant);
|
||||
}
|
||||
|
||||
if let Some(source) = important_style_attr {
|
||||
current = current.ensure_child(self.root.downgrade(), source, StyleAttributeImportant);
|
||||
}
|
||||
|
||||
for source in important_user.into_iter() {
|
||||
current = current.ensure_child(self.root.downgrade(), source, UserImportant);
|
||||
}
|
||||
|
||||
for source in important_ua.into_iter() {
|
||||
current = current.ensure_child(self.root.downgrade(), source, UAImportant);
|
||||
}
|
||||
|
||||
if let Some(source) = transition {
|
||||
current = current.ensure_child(self.root.downgrade(), source, Transitions);
|
||||
}
|
||||
|
||||
current
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue