1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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, NodeExt};
use crate::dom_traversal::iter_child_nodes;
pub struct RecalcStyle<'a> {
context: &'a LayoutContext<'a>,
}
impl<'a> RecalcStyle<'a> {
pub fn new(context: &'a LayoutContext<'a>) -> Self {
RecalcStyle { context }
}
pub fn context(&self) -> &LayoutContext<'a> {
self.context
}
}
#[allow(unsafe_code)]
impl<'dom, E> DomTraversal<E> for RecalcStyle<'_>
where
E: TElement,
E::ConcreteNode: 'dom + LayoutNode<'dom>,
{
fn process_preorder<F>(
&self,
traversal_data: &PerLevelTraversalData,
context: &mut StyleContext<E>,
node: E::ConcreteNode,
note_child: F,
) 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>();
}
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();
}
}
#[inline]
fn needs_postorder_traversal() -> bool {
false
}
fn process_postorder(&self, _style_context: &mut StyleContext<E>, _node: E::ConcreteNode) {
panic!("this should never be called")
}
fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool {
node.layout_data().is_none() || !parent_data.damage.is_empty()
}
fn shared_context(&self) -> &SharedStyleContext {
&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
}
|