mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
style: Remove a few more unuseful traversals now we can.
This commit is contained in:
parent
354dc66029
commit
c3a727ebda
5 changed files with 64 additions and 73 deletions
|
@ -1097,12 +1097,16 @@ impl LayoutThread {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
|
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
|
||||||
for node in node.traverse_preorder() {
|
let mut iter = node.traverse_preorder();
|
||||||
|
|
||||||
|
let mut next = iter.next();
|
||||||
|
while let Some(node) = next {
|
||||||
if node.needs_dirty_on_viewport_size_changed() {
|
if node.needs_dirty_on_viewport_size_changed() {
|
||||||
node.dirty_self();
|
// NB: The dirty bit is propagated down the tree.
|
||||||
node.dirty_descendants();
|
unsafe { node.set_dirty(true); }
|
||||||
// TODO(shinglyu): We can skip the traversal if the descendants were already
|
next = iter.next_skipping_children();
|
||||||
// dirtied
|
} else {
|
||||||
|
next = iter.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1118,9 @@ impl LayoutThread {
|
||||||
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
let needs_reflow = viewport_size_changed && !needs_dirtying;
|
||||||
unsafe {
|
unsafe {
|
||||||
if needs_dirtying {
|
if needs_dirtying {
|
||||||
LayoutThread::dirty_all_nodes(node);
|
// NB: The dirty flag is propagated down during the restyle
|
||||||
|
// process.
|
||||||
|
node.set_dirty(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needs_reflow {
|
if needs_reflow {
|
||||||
|
|
|
@ -1287,6 +1287,31 @@ impl TreeIterator {
|
||||||
depth: 0,
|
depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_skipping_children(&mut self) -> Option<Root<Node>> {
|
||||||
|
let current = match self.current.take() {
|
||||||
|
None => return None,
|
||||||
|
Some(current) => current,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.next_skipping_children_impl(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_skipping_children_impl(&mut self, current: Root<Node>) -> Option<Root<Node>> {
|
||||||
|
for ancestor in current.inclusive_ancestors() {
|
||||||
|
if self.depth == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if let Some(next_sibling) = ancestor.GetNextSibling() {
|
||||||
|
self.current = Some(next_sibling);
|
||||||
|
return Some(current);
|
||||||
|
}
|
||||||
|
self.depth -= 1;
|
||||||
|
}
|
||||||
|
debug_assert!(self.depth == 0);
|
||||||
|
self.current = None;
|
||||||
|
Some(current)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for TreeIterator {
|
impl Iterator for TreeIterator {
|
||||||
|
@ -1303,19 +1328,8 @@ impl Iterator for TreeIterator {
|
||||||
self.depth += 1;
|
self.depth += 1;
|
||||||
return Some(current);
|
return Some(current);
|
||||||
};
|
};
|
||||||
for ancestor in current.inclusive_ancestors() {
|
|
||||||
if self.depth == 0 {
|
self.next_skipping_children_impl(current)
|
||||||
break;
|
|
||||||
}
|
|
||||||
if let Some(next_sibling) = ancestor.GetNextSibling() {
|
|
||||||
self.current = Some(next_sibling);
|
|
||||||
return Some(current);
|
|
||||||
}
|
|
||||||
self.depth -= 1;
|
|
||||||
}
|
|
||||||
debug_assert!(self.depth == 0);
|
|
||||||
self.current = None;
|
|
||||||
Some(current)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,15 +199,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
||||||
self.node.set_flag(DIRTY_ON_VIEWPORT_SIZE_CHANGE, true);
|
self.node.set_flag(DIRTY_ON_VIEWPORT_SIZE_CHANGE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_descendants_dirty_on_viewport_size_changed(&self) {
|
|
||||||
for ref child in self.children() {
|
|
||||||
unsafe {
|
|
||||||
child.set_dirty_on_viewport_size_changed();
|
|
||||||
}
|
|
||||||
child.set_descendants_dirty_on_viewport_size_changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_be_fragmented(&self) -> bool {
|
fn can_be_fragmented(&self) -> bool {
|
||||||
unsafe { self.node.get_flag(CAN_BE_FRAGMENTED) }
|
unsafe { self.node.get_flag(CAN_BE_FRAGMENTED) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,33 +111,10 @@ pub trait TNode : Sized + Copy + Clone {
|
||||||
|
|
||||||
unsafe fn set_dirty_descendants(&self, value: bool);
|
unsafe fn set_dirty_descendants(&self, value: bool);
|
||||||
|
|
||||||
fn dirty_self(&self) {
|
|
||||||
unsafe {
|
|
||||||
self.set_dirty(true);
|
|
||||||
self.set_dirty_descendants(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dirty_descendants(&self) {
|
|
||||||
for ref child in self.children() {
|
|
||||||
child.dirty_self();
|
|
||||||
child.dirty_descendants();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn needs_dirty_on_viewport_size_changed(&self) -> bool;
|
fn needs_dirty_on_viewport_size_changed(&self) -> bool;
|
||||||
|
|
||||||
unsafe fn set_dirty_on_viewport_size_changed(&self);
|
unsafe fn set_dirty_on_viewport_size_changed(&self);
|
||||||
|
|
||||||
fn set_descendants_dirty_on_viewport_size_changed(&self) {
|
|
||||||
for ref child in self.children() {
|
|
||||||
unsafe {
|
|
||||||
child.set_dirty_on_viewport_size_changed();
|
|
||||||
}
|
|
||||||
child.set_descendants_dirty_on_viewport_size_changed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_be_fragmented(&self) -> bool;
|
fn can_be_fragmented(&self) -> bool;
|
||||||
|
|
||||||
unsafe fn set_can_be_fragmented(&self, value: bool);
|
unsafe fn set_can_be_fragmented(&self, value: bool);
|
||||||
|
@ -215,7 +192,7 @@ pub trait TElement : Sized + Copy + Clone + ElementExt + PresentationalHintsSynt
|
||||||
fn attr_equals(&self, namespace: &Namespace, attr: &Atom, value: &Atom) -> bool;
|
fn attr_equals(&self, namespace: &Namespace, attr: &Atom, value: &Atom) -> bool;
|
||||||
|
|
||||||
/// Properly marks nodes as dirty in response to restyle hints.
|
/// Properly marks nodes as dirty in response to restyle hints.
|
||||||
fn note_restyle_hint(&self, mut hint: RestyleHint) {
|
fn note_restyle_hint(&self, hint: RestyleHint) {
|
||||||
// Bail early if there's no restyling to do.
|
// Bail early if there's no restyling to do.
|
||||||
if hint.is_empty() {
|
if hint.is_empty() {
|
||||||
return;
|
return;
|
||||||
|
@ -233,23 +210,21 @@ pub trait TElement : Sized + Copy + Clone + ElementExt + PresentationalHintsSynt
|
||||||
|
|
||||||
// Process hints.
|
// Process hints.
|
||||||
if hint.contains(RESTYLE_SELF) {
|
if hint.contains(RESTYLE_SELF) {
|
||||||
node.dirty_self();
|
unsafe { node.set_dirty(true); }
|
||||||
|
// XXX(emilio): For now, dirty implies dirty descendants if found.
|
||||||
|
} else if hint.contains(RESTYLE_DESCENDANTS) {
|
||||||
|
let mut current = node.first_child();
|
||||||
|
while let Some(node) = current {
|
||||||
|
unsafe { node.set_dirty(true); }
|
||||||
|
current = node.next_sibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(bholley, #8438): We currently need to RESTYLE_DESCENDANTS in the
|
|
||||||
// RESTYLE_SELF case in order to make sure "inherit" style structs propagate
|
|
||||||
// properly. See the explanation in the github issue.
|
|
||||||
hint.insert(RESTYLE_DESCENDANTS);
|
|
||||||
}
|
|
||||||
if hint.contains(RESTYLE_DESCENDANTS) {
|
|
||||||
unsafe { node.set_dirty_descendants(true); }
|
|
||||||
node.dirty_descendants();
|
|
||||||
}
|
|
||||||
if hint.contains(RESTYLE_LATER_SIBLINGS) {
|
if hint.contains(RESTYLE_LATER_SIBLINGS) {
|
||||||
let mut next = ::selectors::Element::next_sibling_element(self);
|
let mut next = ::selectors::Element::next_sibling_element(self);
|
||||||
while let Some(sib) = next {
|
while let Some(sib) = next {
|
||||||
let sib_node = sib.as_node();
|
let sib_node = sib.as_node();
|
||||||
sib_node.dirty_self();
|
unsafe { sib_node.set_dirty(true) };
|
||||||
sib_node.dirty_descendants();
|
|
||||||
next = ::selectors::Element::next_sibling_element(&sib);
|
next = ::selectors::Element::next_sibling_element(&sib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,12 +237,16 @@ pub struct TreeIterator<ConcreteNode> where ConcreteNode: TNode {
|
||||||
|
|
||||||
impl<ConcreteNode> TreeIterator<ConcreteNode> where ConcreteNode: TNode {
|
impl<ConcreteNode> TreeIterator<ConcreteNode> where ConcreteNode: TNode {
|
||||||
fn new(root: ConcreteNode) -> TreeIterator<ConcreteNode> {
|
fn new(root: ConcreteNode) -> TreeIterator<ConcreteNode> {
|
||||||
let mut stack = vec!();
|
let mut stack = vec![];
|
||||||
stack.push(root);
|
stack.push(root);
|
||||||
TreeIterator {
|
TreeIterator {
|
||||||
stack: stack,
|
stack: stack,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_skipping_children(&mut self) -> Option<ConcreteNode> {
|
||||||
|
self.stack.pop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ConcreteNode> Iterator for TreeIterator<ConcreteNode>
|
impl<ConcreteNode> Iterator for TreeIterator<ConcreteNode>
|
||||||
|
|
|
@ -268,16 +268,17 @@ pub fn recalc_style_at<'a, N, C>(context: &'a C,
|
||||||
// NB: flow construction updates the bloom filter on the way up.
|
// NB: flow construction updates the bloom filter on the way up.
|
||||||
put_thread_local_bloom_filter(bf, &unsafe_layout_node, context.shared_context());
|
put_thread_local_bloom_filter(bf, &unsafe_layout_node, context.shared_context());
|
||||||
|
|
||||||
// Mark the node as DIRTY_ON_VIEWPORT_SIZE_CHANGE is it uses viewport percentage units.
|
// Mark the node as DIRTY_ON_VIEWPORT_SIZE_CHANGE is it uses viewport
|
||||||
if let Some(element) = node.as_element() {
|
// percentage units.
|
||||||
if let Some(ref property_declaration_block) = *element.style_attribute() {
|
if !node.needs_dirty_on_viewport_size_changed() {
|
||||||
if property_declaration_block.declarations().any(|d| d.0.has_viewport_percentage()) {
|
if let Some(element) = node.as_element() {
|
||||||
unsafe {
|
if let Some(ref property_declaration_block) = *element.style_attribute() {
|
||||||
node.set_dirty_on_viewport_size_changed();
|
if property_declaration_block.declarations().any(|d| d.0.has_viewport_percentage()) {
|
||||||
|
unsafe {
|
||||||
|
node.set_dirty_on_viewport_size_changed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
node.set_descendants_dirty_on_viewport_size_changed();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue