mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Rollup merge of #17014 - hiikezoe:animation-rules-in-norma-restyle, r=emilio,birtles
Animation rules in norma restyle <!-- Please describe your changes on the following line: --> This is a PR for https://bugzilla.mozilla.org/show_bug.cgi?id=1366631 and https://bugzilla.mozilla.org/show_bug.cgi?id=1367225 - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes do not require tests because it's for stylo <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17014) <!-- Reviewable:end -->
This commit is contained in:
commit
a19dd8142e
8 changed files with 231 additions and 149 deletions
|
@ -10,10 +10,10 @@
|
|||
use cascade_info::CascadeInfo;
|
||||
use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
|
||||
use data::{ComputedStyle, ElementData, RestyleData};
|
||||
use dom::{AnimationRules, TElement, TNode};
|
||||
use dom::{TElement, TNode};
|
||||
use font_metrics::FontMetricsProvider;
|
||||
use log::LogLevel::Trace;
|
||||
use properties::{CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
||||
use properties::{AnimationRules, CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
||||
use properties::longhands::display::computed_value as display;
|
||||
use restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS, RestyleReplacements};
|
||||
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_SMIL};
|
||||
|
@ -254,12 +254,15 @@ trait PrivateMatchMethods: TElement {
|
|||
// We could make that a bit better if the complexity cost is not too
|
||||
// big, but given further restyles are posted directly to
|
||||
// pseudo-elements, it doesn't seem worth the effort at a glance.
|
||||
if pseudo.is_eager() && self.get_animation_rules().is_empty() {
|
||||
if pseudo.is_eager() {
|
||||
let parent = self.parent_element().unwrap();
|
||||
let parent_data = parent.borrow_data().unwrap();
|
||||
let pseudo_style =
|
||||
parent_data.styles().pseudos.get(&pseudo).unwrap();
|
||||
return pseudo_style.values().clone()
|
||||
if !parent.may_have_animations() ||
|
||||
primary_style.rules.get_animation_rules().is_empty() {
|
||||
let parent_data = parent.borrow_data().unwrap();
|
||||
let pseudo_style =
|
||||
parent_data.styles().pseudos.get(&pseudo).unwrap();
|
||||
return pseudo_style.values().clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -694,38 +697,39 @@ pub trait MatchMethods : TElement {
|
|||
let pseudo_style =
|
||||
parent_data.styles().pseudos.get(&pseudo).unwrap();
|
||||
let mut rules = pseudo_style.rules.clone();
|
||||
let animation_rules = self.get_animation_rules();
|
||||
if parent.may_have_animations() {
|
||||
let animation_rules = data.get_animation_rules();
|
||||
|
||||
// Handle animations here.
|
||||
if let Some(animation_rule) = animation_rules.0 {
|
||||
let animation_rule_node =
|
||||
context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(CascadeLevel::Animations,
|
||||
Some(&animation_rule),
|
||||
&mut rules,
|
||||
&context.shared.guards);
|
||||
if let Some(node) = animation_rule_node {
|
||||
rules = node;
|
||||
// Handle animations here.
|
||||
if let Some(animation_rule) = animation_rules.0 {
|
||||
let animation_rule_node =
|
||||
context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(CascadeLevel::Animations,
|
||||
Some(&animation_rule),
|
||||
&mut rules,
|
||||
&context.shared.guards);
|
||||
if let Some(node) = animation_rule_node {
|
||||
rules = node;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(animation_rule) = animation_rules.1 {
|
||||
let animation_rule_node =
|
||||
context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(CascadeLevel::Transitions,
|
||||
Some(&animation_rule),
|
||||
&mut rules,
|
||||
&context.shared.guards);
|
||||
if let Some(node) = animation_rule_node {
|
||||
rules = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(animation_rule) = animation_rules.1 {
|
||||
let animation_rule_node =
|
||||
context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(CascadeLevel::Transitions,
|
||||
Some(&animation_rule),
|
||||
&mut rules,
|
||||
&context.shared.guards);
|
||||
if let Some(node) = animation_rule_node {
|
||||
rules = node;
|
||||
}
|
||||
}
|
||||
|
||||
let important_rules_changed =
|
||||
self.has_animations() &&
|
||||
data.has_styles() &&
|
||||
data.important_rules_are_different(&rules,
|
||||
&context.shared.guards);
|
||||
&context.shared.guards);
|
||||
|
||||
return RulesMatchedResult {
|
||||
rule_nodes_changed: data.set_primary_rules(rules),
|
||||
|
@ -738,30 +742,35 @@ pub trait MatchMethods : TElement {
|
|||
|
||||
let stylist = &context.shared.stylist;
|
||||
let style_attribute = self.style_attribute();
|
||||
let smil_override = self.get_smil_override();
|
||||
let animation_rules = self.get_animation_rules();
|
||||
let bloom = context.thread_local.bloom_filter.filter();
|
||||
{
|
||||
let smil_override = data.get_smil_override();
|
||||
let animation_rules = if self.may_have_animations() {
|
||||
data.get_animation_rules()
|
||||
} else {
|
||||
AnimationRules(None, None)
|
||||
};
|
||||
let bloom = context.thread_local.bloom_filter.filter();
|
||||
|
||||
let map = &mut context.thread_local.selector_flags;
|
||||
let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| {
|
||||
self.apply_selector_flags(map, element, flags);
|
||||
};
|
||||
|
||||
let map = &mut context.thread_local.selector_flags;
|
||||
let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| {
|
||||
self.apply_selector_flags(map, element, flags);
|
||||
};
|
||||
let mut matching_context =
|
||||
MatchingContext::new(MatchingMode::Normal, Some(bloom));
|
||||
|
||||
let mut matching_context =
|
||||
MatchingContext::new(MatchingMode::Normal, Some(bloom));
|
||||
// Compute the primary rule node.
|
||||
stylist.push_applicable_declarations(self,
|
||||
implemented_pseudo.as_ref(),
|
||||
style_attribute,
|
||||
smil_override,
|
||||
animation_rules,
|
||||
&mut applicable_declarations,
|
||||
&mut matching_context,
|
||||
&mut set_selector_flags);
|
||||
|
||||
// Compute the primary rule node.
|
||||
stylist.push_applicable_declarations(self,
|
||||
implemented_pseudo.as_ref(),
|
||||
style_attribute,
|
||||
smil_override,
|
||||
animation_rules,
|
||||
&mut applicable_declarations,
|
||||
&mut matching_context,
|
||||
&mut set_selector_flags);
|
||||
|
||||
*relations = matching_context.relations;
|
||||
*relations = matching_context.relations;
|
||||
}
|
||||
|
||||
let primary_rule_node =
|
||||
compute_rule_node::<Self>(stylist.rule_tree(),
|
||||
|
@ -965,81 +974,82 @@ pub trait MatchMethods : TElement {
|
|||
}
|
||||
|
||||
/// Updates the rule nodes without re-running selector matching, using just
|
||||
/// the rule tree. Returns RulesChanged which indicates whether the rule nodes changed
|
||||
/// and whether the important rules changed.
|
||||
/// the rule tree. Returns true if an !important rule was replaced.
|
||||
fn replace_rules(&self,
|
||||
replacements: RestyleReplacements,
|
||||
context: &StyleContext<Self>,
|
||||
data: &mut ElementData)
|
||||
-> RulesChanged {
|
||||
-> bool {
|
||||
use properties::PropertyDeclarationBlock;
|
||||
use shared_lock::Locked;
|
||||
|
||||
let element_styles = &mut data.styles_mut();
|
||||
let primary_rules = &mut element_styles.primary.rules;
|
||||
let mut result = RulesChanged::empty();
|
||||
|
||||
{
|
||||
let mut replace_rule_node = |level: CascadeLevel,
|
||||
pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
|
||||
path: &mut StrongRuleNode| {
|
||||
let new_node = context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(level, pdb, path, &context.shared.guards);
|
||||
if let Some(n) = new_node {
|
||||
let replace_rule_node = |level: CascadeLevel,
|
||||
pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
|
||||
path: &mut StrongRuleNode| -> bool {
|
||||
let new_node = context.shared.stylist.rule_tree()
|
||||
.update_rule_at_level(level, pdb, path, &context.shared.guards);
|
||||
match new_node {
|
||||
Some(n) => {
|
||||
*path = n;
|
||||
if level.is_important() {
|
||||
result.insert(IMPORTANT_RULES_CHANGED);
|
||||
} else {
|
||||
result.insert(NORMAL_RULES_CHANGED);
|
||||
}
|
||||
}
|
||||
level.is_important()
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
};
|
||||
|
||||
if !context.shared.traversal_flags.for_animation_only() {
|
||||
let mut result = false;
|
||||
if replacements.contains(RESTYLE_STYLE_ATTRIBUTE) {
|
||||
let style_attribute = self.style_attribute();
|
||||
result |= replace_rule_node(CascadeLevel::StyleAttributeNormal,
|
||||
style_attribute,
|
||||
primary_rules);
|
||||
result |= replace_rule_node(CascadeLevel::StyleAttributeImportant,
|
||||
style_attribute,
|
||||
primary_rules);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Animation restyle hints are processed prior to other restyle
|
||||
// hints in the animation-only traversal.
|
||||
//
|
||||
// Non-animation restyle hints will be processed in a subsequent
|
||||
// normal traversal.
|
||||
if replacements.intersects(RestyleReplacements::for_animations()) {
|
||||
debug_assert!(context.shared.traversal_flags.for_animation_only());
|
||||
|
||||
if replacements.contains(RESTYLE_SMIL) {
|
||||
replace_rule_node(CascadeLevel::SMILOverride,
|
||||
self.get_smil_override(),
|
||||
primary_rules);
|
||||
}
|
||||
|
||||
let replace_rule_node_for_animation = |level: CascadeLevel,
|
||||
primary_rules: &mut StrongRuleNode| {
|
||||
let animation_rule = self.get_animation_rule_by_cascade(level);
|
||||
replace_rule_node(level,
|
||||
animation_rule.as_ref(),
|
||||
primary_rules);
|
||||
};
|
||||
|
||||
// Animation restyle hints are processed prior to other restyle
|
||||
// hints in the animation-only traversal.
|
||||
//
|
||||
// Non-animation restyle hints will be processed in a subsequent
|
||||
// normal traversal.
|
||||
if replacements.intersects(RestyleReplacements::for_animations()) {
|
||||
debug_assert!(context.shared.traversal_flags.for_animation_only());
|
||||
// Apply Transition rules and Animation rules if the corresponding restyle hint
|
||||
// is contained.
|
||||
if replacements.contains(RESTYLE_CSS_TRANSITIONS) {
|
||||
replace_rule_node_for_animation(CascadeLevel::Transitions,
|
||||
primary_rules);
|
||||
}
|
||||
|
||||
if replacements.contains(RESTYLE_SMIL) {
|
||||
replace_rule_node(CascadeLevel::SMILOverride,
|
||||
self.get_smil_override(),
|
||||
primary_rules);
|
||||
}
|
||||
|
||||
let mut replace_rule_node_for_animation = |level: CascadeLevel,
|
||||
primary_rules: &mut StrongRuleNode| {
|
||||
let animation_rule = self.get_animation_rule_by_cascade(level);
|
||||
replace_rule_node(level,
|
||||
animation_rule.as_ref(),
|
||||
primary_rules);
|
||||
};
|
||||
|
||||
// Apply Transition rules and Animation rules if the corresponding restyle hint
|
||||
// is contained.
|
||||
if replacements.contains(RESTYLE_CSS_TRANSITIONS) {
|
||||
replace_rule_node_for_animation(CascadeLevel::Transitions,
|
||||
primary_rules);
|
||||
}
|
||||
|
||||
if replacements.contains(RESTYLE_CSS_ANIMATIONS) {
|
||||
replace_rule_node_for_animation(CascadeLevel::Animations,
|
||||
primary_rules);
|
||||
}
|
||||
} else if replacements.contains(RESTYLE_STYLE_ATTRIBUTE) {
|
||||
let style_attribute = self.style_attribute();
|
||||
replace_rule_node(CascadeLevel::StyleAttributeNormal,
|
||||
style_attribute,
|
||||
primary_rules);
|
||||
replace_rule_node(CascadeLevel::StyleAttributeImportant,
|
||||
style_attribute,
|
||||
primary_rules);
|
||||
if replacements.contains(RESTYLE_CSS_ANIMATIONS) {
|
||||
replace_rule_node_for_animation(CascadeLevel::Animations,
|
||||
primary_rules);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
false
|
||||
}
|
||||
|
||||
/// Attempts to share a style with another node. This method is unsafe
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue