Add SMIL override cascade level

This commit is contained in:
Brian Birtles 2017-04-27 12:35:12 +09:00
parent 18c72ac28d
commit 97ce9ed5b0
4 changed files with 49 additions and 14 deletions

View file

@ -319,6 +319,11 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
/// Get this element's style attribute. /// Get this element's style attribute.
fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>; fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>;
/// Get this element's SMIL override declarations.
fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
None
}
/// Get this element's animation rules. /// Get this element's animation rules.
fn get_animation_rules(&self, _pseudo: Option<&PseudoElement>) -> AnimationRules { fn get_animation_rules(&self, _pseudo: Option<&PseudoElement>) -> AnimationRules {
AnimationRules(None, None) AnimationRules(None, None)

View file

@ -882,6 +882,7 @@ pub trait MatchMethods : TElement {
let stylist = &context.shared.stylist; let stylist = &context.shared.stylist;
let style_attribute = self.style_attribute(); let style_attribute = self.style_attribute();
let smil_override = self.get_smil_override();
let animation_rules = self.get_animation_rules(None); let animation_rules = self.get_animation_rules(None);
let mut rule_nodes_changed = false; let mut rule_nodes_changed = false;
let bloom = context.thread_local.bloom_filter.filter(); let bloom = context.thread_local.bloom_filter.filter();
@ -895,6 +896,7 @@ pub trait MatchMethods : TElement {
*relations = stylist.push_applicable_declarations(self, *relations = stylist.push_applicable_declarations(self,
Some(bloom), Some(bloom),
style_attribute, style_attribute,
smil_override,
animation_rules, animation_rules,
None, None,
&context.shared.guards, &context.shared.guards,
@ -952,7 +954,9 @@ pub trait MatchMethods : TElement {
}; };
stylist.push_applicable_declarations(self, stylist.push_applicable_declarations(self,
Some(bloom_filter), Some(bloom_filter),
None, pseudo_animation_rules, None,
None,
pseudo_animation_rules,
Some(&pseudo), Some(&pseudo),
&guards, &guards,
&mut applicable_declarations, &mut applicable_declarations,

View file

@ -254,19 +254,19 @@ impl RuleTree {
path.parent().unwrap().clone() path.parent().unwrap().clone()
} }
/// Returns new rule node without Animations and Transitions level rules. /// Returns new rule node without rules from declarative animations.
pub fn remove_animation_and_transition_rules(&self, path: &StrongRuleNode) -> StrongRuleNode { pub fn remove_animation_and_transition_rules(&self, path: &StrongRuleNode) -> StrongRuleNode {
// Return a clone if there is neither animation nor transition level. // Return a clone if there are no animation rules.
if !path.has_animation_or_transition_rules() { if !path.has_animation_or_transition_rules() {
return path.clone(); return path.clone();
} }
let iter = path.self_and_ancestors().take_while(|node| node.cascade_level() >= CascadeLevel::Animations); let iter = path.self_and_ancestors().take_while(
|node| node.cascade_level() >= CascadeLevel::SMILOverride);
let mut last = path; let mut last = path;
let mut children = vec![]; let mut children = vec![];
for node in iter { for node in iter {
if node.cascade_level() != CascadeLevel::Animations && if node.cascade_level().is_animation() {
node.cascade_level() != CascadeLevel::Transitions {
children.push((node.get().source.clone().unwrap(), node.cascade_level())); children.push((node.get().source.clone().unwrap(), node.cascade_level()));
} }
last = node; last = node;
@ -301,6 +301,8 @@ pub enum CascadeLevel {
AuthorNormal, AuthorNormal,
/// Style attribute normal rules. /// Style attribute normal rules.
StyleAttributeNormal, StyleAttributeNormal,
/// SVG SMIL animations.
SMILOverride,
/// CSS animations and script-generated animations. /// CSS animations and script-generated animations.
Animations, Animations,
/// Author-supplied important rules. /// Author-supplied important rules.
@ -333,6 +335,7 @@ impl CascadeLevel {
match *self { match *self {
CascadeLevel::Transitions | CascadeLevel::Transitions |
CascadeLevel::Animations | CascadeLevel::Animations |
CascadeLevel::SMILOverride |
CascadeLevel::StyleAttributeNormal | CascadeLevel::StyleAttributeNormal |
CascadeLevel::StyleAttributeImportant => true, CascadeLevel::StyleAttributeImportant => true,
_ => false, _ => false,
@ -362,6 +365,17 @@ impl CascadeLevel {
Importance::Normal Importance::Normal
} }
} }
/// Returns whether this cascade level represents an animation rules.
#[inline]
pub fn is_animation(&self) -> bool {
match *self {
CascadeLevel::SMILOverride |
CascadeLevel::Animations |
CascadeLevel::Transitions => true,
_ => false,
}
}
} }
struct RuleNode { struct RuleNode {
@ -780,8 +794,8 @@ impl StrongRuleNode {
/// Returns true if there is either animation or transition level rule. /// Returns true if there is either animation or transition level rule.
pub fn has_animation_or_transition_rules(&self) -> bool { pub fn has_animation_or_transition_rules(&self) -> bool {
self.self_and_ancestors() self.self_and_ancestors()
.take_while(|node| node.cascade_level() >= CascadeLevel::Animations) .take_while(|node| node.cascade_level() >= CascadeLevel::SMILOverride)
.any(|node| matches!(node.cascade_level(), CascadeLevel::Animations | CascadeLevel::Transitions)) .any(|node| node.cascade_level().is_animation())
} }
} }

View file

@ -510,6 +510,7 @@ impl Stylist {
self.push_applicable_declarations(element, self.push_applicable_declarations(element,
None,
None, None,
None, None,
AnimationRules(None, None), AnimationRules(None, None),
@ -631,6 +632,7 @@ impl Stylist {
element: &E, element: &E,
parent_bf: Option<&BloomFilter>, parent_bf: Option<&BloomFilter>,
style_attribute: Option<&Arc<Locked<PropertyDeclarationBlock>>>, style_attribute: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
smil_override: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
animation_rules: AnimationRules, animation_rules: AnimationRules,
pseudo_element: Option<&PseudoElement>, pseudo_element: Option<&PseudoElement>,
guards: &StylesheetGuards, guards: &StylesheetGuards,
@ -711,7 +713,17 @@ impl Stylist {
debug!("style attr: {:?}", relations); debug!("style attr: {:?}", relations);
// Step 5: Animations. // Step 5: SMIL override.
// Declarations from SVG SMIL animation elements.
if let Some(so) = smil_override {
Push::push(
applicable_declarations,
ApplicableDeclarationBlock::from_declarations(so.clone(),
CascadeLevel::SMILOverride));
}
debug!("SMIL: {:?}", relations);
// Step 6: Animations.
// The animations sheet (CSS animations, script-generated animations, // The animations sheet (CSS animations, script-generated animations,
// and CSS transitions that are no longer tied to CSS markup) // and CSS transitions that are no longer tied to CSS markup)
if let Some(anim) = animation_rules.0 { if let Some(anim) = animation_rules.0 {
@ -722,7 +734,7 @@ impl Stylist {
} }
debug!("animation: {:?}", relations); debug!("animation: {:?}", relations);
// Step 6: Author-supplied `!important` rules. // Step 7: Author-supplied `!important` rules.
map.author.get_all_matching_rules(element, map.author.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
@ -732,7 +744,7 @@ impl Stylist {
debug!("author important: {:?}", relations); debug!("author important: {:?}", relations);
// Step 7: `!important` style attributes. // Step 8: `!important` style attributes.
if let Some(sa) = style_attribute { if let Some(sa) = style_attribute {
if sa.read_with(guards.author).any_important() { if sa.read_with(guards.author).any_important() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE; relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
@ -745,7 +757,7 @@ impl Stylist {
debug!("style attr important: {:?}", relations); debug!("style attr important: {:?}", relations);
// Step 8: User `!important` rules. // Step 9: User `!important` rules.
map.user.get_all_matching_rules(element, map.user.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
@ -758,7 +770,7 @@ impl Stylist {
debug!("skipping non-agent rules"); debug!("skipping non-agent rules");
} }
// Step 9: UA `!important` rules. // Step 10: UA `!important` rules.
map.user_agent.get_all_matching_rules(element, map.user_agent.get_all_matching_rules(element,
parent_bf, parent_bf,
applicable_declarations, applicable_declarations,
@ -768,7 +780,7 @@ impl Stylist {
debug!("UA important: {:?}", relations); debug!("UA important: {:?}", relations);
// Step 10: Transitions. // Step 11: Transitions.
// The transitions sheet (CSS transitions that are tied to CSS markup) // The transitions sheet (CSS transitions that are tied to CSS markup)
if let Some(anim) = animation_rules.1 { if let Some(anim) = animation_rules.1 {
Push::push( Push::push(