diff options
Diffstat (limited to 'components/layout/traversal.rs')
-rw-r--r-- | components/layout/traversal.rs | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index bf60c41d6ba..17c3d0b1c20 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -2,14 +2,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use script::layout_dom::ServoLayoutNode; use script_layout_interface::wrapper_traits::LayoutNode; use style::context::{SharedStyleContext, StyleContext}; use style::data::ElementData; use style::dom::{NodeInfo, TElement, TNode}; +use style::selector_parser::RestyleDamage; use style::traversal::{DomTraversal, PerLevelTraversalData, recalc_style_at}; +use style::values::computed::Display; use crate::context::LayoutContext; -use crate::dom::DOMLayoutData; +use crate::dom::{DOMLayoutData, NodeExt}; +use crate::dom_traversal::iter_child_nodes; pub struct RecalcStyle<'a> { context: &'a LayoutContext<'a>, @@ -40,14 +44,33 @@ where ) where F: FnMut(E::ConcreteNode), { + if node.is_text_node() { + return; + } + + let had_style_data = node.style_data().is_some(); unsafe { node.initialize_style_and_layout_data::<DOMLayoutData>(); - if !node.is_text_node() { - let el = node.as_element().unwrap(); - let mut data = el.mutate_data().unwrap(); - recalc_style_at(self, traversal_data, context, el, &mut data, note_child); - el.unset_dirty_descendants(); - } + } + + let element = node.as_element().unwrap(); + let mut element_data = element.mutate_data().unwrap(); + + if !had_style_data { + element_data.damage = RestyleDamage::reconstruct(); + } + + recalc_style_at( + self, + traversal_data, + context, + element, + &mut element_data, + note_child, + ); + + unsafe { + element.unset_dirty_descendants(); } } @@ -68,3 +91,48 @@ where &self.context.style_context } } + +pub(crate) fn compute_damage_and_repair_style( + context: &SharedStyleContext, + node: ServoLayoutNode<'_>, +) -> RestyleDamage { + compute_damage_and_repair_style_inner(context, node, RestyleDamage::empty()) +} + +pub(crate) fn compute_damage_and_repair_style_inner( + context: &SharedStyleContext, + node: ServoLayoutNode<'_>, + parent_restyle_damage: RestyleDamage, +) -> RestyleDamage { + let original_damage; + let damage = { + let mut element_data = node + .style_data() + .expect("Should not run `compute_damage` before styling.") + .element_data + .borrow_mut(); + + if let Some(ref style) = element_data.styles.primary { + if style.get_box().display == Display::None { + return parent_restyle_damage; + } + } + + original_damage = std::mem::take(&mut element_data.damage); + element_data.damage |= parent_restyle_damage; + element_data.damage + }; + + let mut propagated_damage = damage; + for child in iter_child_nodes(node) { + if child.is_element() { + propagated_damage |= compute_damage_and_repair_style_inner(context, child, damage); + } + } + + if propagated_damage == RestyleDamage::REPAINT && original_damage == RestyleDamage::REPAINT { + node.repair_style(context); + } + + propagated_damage +} |