mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #16625 - birtles:smil-support, r=hiro,heycam
SMIL support for Gecko PR for [Gecko bug 1355348](https://bugzilla.mozilla.org/show_bug.cgi?id=1355348) --- - [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 they are tested on the Gecko side <!-- 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/16625) <!-- Reviewable:end -->
This commit is contained in:
commit
8824a68063
8 changed files with 89 additions and 30 deletions
|
@ -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)
|
||||||
|
|
|
@ -38,6 +38,7 @@ use gecko_bindings::bindings::Gecko_ElementHasCSSTransitions;
|
||||||
use gecko_bindings::bindings::Gecko_GetAnimationRule;
|
use gecko_bindings::bindings::Gecko_GetAnimationRule;
|
||||||
use gecko_bindings::bindings::Gecko_GetExtraContentStyleDeclarations;
|
use gecko_bindings::bindings::Gecko_GetExtraContentStyleDeclarations;
|
||||||
use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock;
|
use gecko_bindings::bindings::Gecko_GetHTMLPresentationAttrDeclarationBlock;
|
||||||
|
use gecko_bindings::bindings::Gecko_GetSMILOverrideDeclarationBlock;
|
||||||
use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
|
use gecko_bindings::bindings::Gecko_GetStyleAttrDeclarationBlock;
|
||||||
use gecko_bindings::bindings::Gecko_GetStyleContext;
|
use gecko_bindings::bindings::Gecko_GetStyleContext;
|
||||||
use gecko_bindings::bindings::Gecko_IsSignificantChild;
|
use gecko_bindings::bindings::Gecko_IsSignificantChild;
|
||||||
|
@ -525,6 +526,11 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
|
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_smil_override(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
|
||||||
|
let declarations = unsafe { Gecko_GetSMILOverrideDeclarationBlock(self.0) };
|
||||||
|
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
|
||||||
|
}
|
||||||
|
|
||||||
fn get_animation_rules(&self, pseudo: Option<&PseudoElement>) -> AnimationRules {
|
fn get_animation_rules(&self, pseudo: Option<&PseudoElement>) -> AnimationRules {
|
||||||
AnimationRules(self.get_animation_rule(pseudo),
|
AnimationRules(self.get_animation_rule(pseudo),
|
||||||
self.get_transition_rule(pseudo))
|
self.get_transition_rule(pseudo))
|
||||||
|
|
|
@ -623,6 +623,11 @@ extern "C" {
|
||||||
RawServoAnimationValueMapBorrowed)
|
RawServoAnimationValueMapBorrowed)
|
||||||
-> bool;
|
-> bool;
|
||||||
}
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn Gecko_GetSMILOverrideDeclarationBlock(element:
|
||||||
|
RawGeckoElementBorrowed)
|
||||||
|
-> RawServoDeclarationBlockStrongBorrowedOrNull;
|
||||||
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn Gecko_StyleAnimationsEquals(arg1:
|
pub fn Gecko_StyleAnimationsEquals(arg1:
|
||||||
RawGeckoStyleAnimationListBorrowed,
|
RawGeckoStyleAnimationListBorrowed,
|
||||||
|
|
|
@ -19,7 +19,8 @@ use dom::{AnimationRules, SendElement, TElement, TNode};
|
||||||
use font_metrics::FontMetricsProvider;
|
use font_metrics::FontMetricsProvider;
|
||||||
use properties::{CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
use properties::{CascadeFlags, ComputedValues, SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP, cascade};
|
||||||
use properties::longhands::display::computed_value as display;
|
use properties::longhands::display::computed_value as display;
|
||||||
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS, RestyleHint};
|
use restyle_hints::{RESTYLE_CSS_ANIMATIONS, RESTYLE_CSS_TRANSITIONS, RestyleHint};
|
||||||
|
use restyle_hints::{RESTYLE_STYLE_ATTRIBUTE, RESTYLE_SMIL};
|
||||||
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode};
|
use rule_tree::{CascadeLevel, RuleTree, StrongRuleNode};
|
||||||
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
|
use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
|
@ -882,6 +883,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 +897,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 +955,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,
|
||||||
|
@ -1068,12 +1073,18 @@ pub trait MatchMethods : TElement {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// RESTYLE_CSS_ANIMATIONS or RESTYLE_CSS_TRANSITIONS is processed prior to other
|
// Animation restyle hints are processed prior to other restyle hints in the
|
||||||
// restyle hints in the name of animation-only traversal. Rest of restyle hints
|
// animation-only traversal. Non-animation restyle hints will be processed in
|
||||||
// will be processed in a subsequent normal traversal.
|
// a subsequent normal traversal.
|
||||||
if hint.intersects(RestyleHint::for_animations()) {
|
if hint.intersects(RestyleHint::for_animations()) {
|
||||||
debug_assert!(context.shared.traversal_flags.for_animation_only());
|
debug_assert!(context.shared.traversal_flags.for_animation_only());
|
||||||
|
|
||||||
|
if hint.contains(RESTYLE_SMIL) {
|
||||||
|
replace_rule_node(CascadeLevel::SMILOverride,
|
||||||
|
self.get_smil_override(),
|
||||||
|
primary_rules);
|
||||||
|
}
|
||||||
|
|
||||||
use data::EagerPseudoStyles;
|
use data::EagerPseudoStyles;
|
||||||
let mut replace_rule_node_for_animation = |level: CascadeLevel,
|
let mut replace_rule_node_for_animation = |level: CascadeLevel,
|
||||||
primary_rules: &mut StrongRuleNode,
|
primary_rules: &mut StrongRuleNode,
|
||||||
|
@ -1330,7 +1341,7 @@ pub trait MatchMethods : TElement {
|
||||||
let relevant_style = pseudo_style.unwrap_or(primary_style);
|
let relevant_style = pseudo_style.unwrap_or(primary_style);
|
||||||
let rule_node = &relevant_style.rules;
|
let rule_node = &relevant_style.rules;
|
||||||
let without_animation_rules =
|
let without_animation_rules =
|
||||||
shared_context.stylist.rule_tree.remove_animation_and_transition_rules(rule_node);
|
shared_context.stylist.rule_tree.remove_animation_rules(rule_node);
|
||||||
if without_animation_rules == *rule_node {
|
if without_animation_rules == *rule_node {
|
||||||
// Note that unwrapping here is fine, because the style is
|
// Note that unwrapping here is fine, because the style is
|
||||||
// only incomplete during the styling process.
|
// only incomplete during the styling process.
|
||||||
|
|
|
@ -62,6 +62,11 @@ bitflags! {
|
||||||
/// attribute has changed, and this change didn't have any other
|
/// attribute has changed, and this change didn't have any other
|
||||||
/// dependencies.
|
/// dependencies.
|
||||||
const RESTYLE_STYLE_ATTRIBUTE = 0x40,
|
const RESTYLE_STYLE_ATTRIBUTE = 0x40,
|
||||||
|
|
||||||
|
/// Replace the style data coming from SMIL animations without updating
|
||||||
|
/// any other style data. This hint is only processed in animation-only
|
||||||
|
/// traversal which is prior to normal traversal.
|
||||||
|
const RESTYLE_SMIL = 0x80,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,19 +100,22 @@ pub fn assert_restyle_hints_match() {
|
||||||
nsRestyleHint_eRestyle_CSSTransitions => RESTYLE_CSS_TRANSITIONS,
|
nsRestyleHint_eRestyle_CSSTransitions => RESTYLE_CSS_TRANSITIONS,
|
||||||
nsRestyleHint_eRestyle_CSSAnimations => RESTYLE_CSS_ANIMATIONS,
|
nsRestyleHint_eRestyle_CSSAnimations => RESTYLE_CSS_ANIMATIONS,
|
||||||
nsRestyleHint_eRestyle_StyleAttribute => RESTYLE_STYLE_ATTRIBUTE,
|
nsRestyleHint_eRestyle_StyleAttribute => RESTYLE_STYLE_ATTRIBUTE,
|
||||||
|
nsRestyleHint_eRestyle_StyleAttribute_Animations => RESTYLE_SMIL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RestyleHint {
|
impl RestyleHint {
|
||||||
/// The subset hints that affect the styling of a single element during the
|
/// The subset hints that affect the styling of a single element during the
|
||||||
/// traversal.
|
/// traversal.
|
||||||
|
#[inline]
|
||||||
pub fn for_self() -> Self {
|
pub fn for_self() -> Self {
|
||||||
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE | RESTYLE_CSS_ANIMATIONS | RESTYLE_CSS_TRANSITIONS
|
RESTYLE_SELF | RESTYLE_STYLE_ATTRIBUTE | Self::for_animations()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The subset hints that are used for animation restyle.
|
/// The subset hints that are used for animation restyle.
|
||||||
|
#[inline]
|
||||||
pub fn for_animations() -> Self {
|
pub fn for_animations() -> Self {
|
||||||
RESTYLE_CSS_ANIMATIONS | RESTYLE_CSS_TRANSITIONS
|
RESTYLE_SMIL | RESTYLE_CSS_ANIMATIONS | RESTYLE_CSS_TRANSITIONS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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_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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -1795,19 +1795,17 @@ pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
|
||||||
let damage = GeckoRestyleDamage::new(change_hint);
|
let damage = GeckoRestyleDamage::new(change_hint);
|
||||||
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
|
debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
|
||||||
element, restyle_hint, change_hint);
|
element, restyle_hint, change_hint);
|
||||||
debug_assert!(restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations ||
|
|
||||||
restyle_hint == structs::nsRestyleHint_eRestyle_CSSTransitions ||
|
let restyle_hint: RestyleHint = restyle_hint.into();
|
||||||
(restyle_hint.0 & (structs::nsRestyleHint_eRestyle_CSSAnimations.0 |
|
debug_assert!(RestyleHint::for_animations().contains(restyle_hint) ||
|
||||||
structs::nsRestyleHint_eRestyle_CSSTransitions.0)) == 0,
|
!RestyleHint::for_animations().intersects(restyle_hint),
|
||||||
"eRestyle_CSSAnimations or eRestyle_CSSTransitions should only appear by itself");
|
"Animation restyle hints should not appear with non-animation restyle hints");
|
||||||
|
|
||||||
let mut maybe_data = element.mutate_data();
|
let mut maybe_data = element.mutate_data();
|
||||||
let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
|
let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
|
||||||
maybe_restyle(d, element, restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations ||
|
maybe_restyle(d, element, restyle_hint.intersects(RestyleHint::for_animations()))
|
||||||
restyle_hint == structs::nsRestyleHint_eRestyle_CSSTransitions)
|
|
||||||
});
|
});
|
||||||
if let Some(restyle_data) = maybe_restyle_data {
|
if let Some(restyle_data) = maybe_restyle_data {
|
||||||
let restyle_hint: RestyleHint = restyle_hint.into();
|
|
||||||
restyle_data.hint.insert(&restyle_hint.into());
|
restyle_data.hint.insert(&restyle_hint.into());
|
||||||
restyle_data.damage |= damage;
|
restyle_data.damage |= damage;
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue