mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Rewrite handling of pointers to boxes in the DOM tree
This commit is contained in:
parent
c43ab0c267
commit
3e8623332b
3 changed files with 33 additions and 73 deletions
|
@ -110,25 +110,21 @@ fn traverse_element<'dom, Node>(
|
||||||
let replaced = ReplacedContent::for_element(element);
|
let replaced = ReplacedContent::for_element(element);
|
||||||
let style = element.style(context);
|
let style = element.style(context);
|
||||||
match Display::from(style.get_box().display) {
|
match Display::from(style.get_box().display) {
|
||||||
Display::None => element.unset_boxes_in_subtree(),
|
Display::None => element.unset_all_boxes(),
|
||||||
Display::Contents => {
|
Display::Contents => {
|
||||||
if replaced.is_some() {
|
if replaced.is_some() {
|
||||||
// `display: content` on a replaced element computes to `display: none`
|
// `display: content` on a replaced element computes to `display: none`
|
||||||
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
|
||||||
element.unset_boxes_in_subtree()
|
element.unset_all_boxes()
|
||||||
} else {
|
} else {
|
||||||
*element.layout_data_mut().self_box.borrow_mut() = Some(LayoutBox::DisplayContents);
|
element.element_box_slot().set(LayoutBox::DisplayContents);
|
||||||
traverse_children_of(element, context, handler)
|
traverse_children_of(element, context, handler)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Display::GeneratingBox(display) => {
|
Display::GeneratingBox(display) => {
|
||||||
handler.handle_element(
|
let contents = replaced.map_or(Contents::OfElement, Contents::Replaced);
|
||||||
element,
|
let box_slot = element.element_box_slot();
|
||||||
&style,
|
handler.handle_element(element, &style, display, contents, box_slot);
|
||||||
display,
|
|
||||||
replaced.map_or(Contents::OfElement, Contents::Replaced),
|
|
||||||
element.element_box_slot(),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,17 +141,20 @@ fn traverse_pseudo_element<'dom, Node>(
|
||||||
match Display::from(style.get_box().display) {
|
match Display::from(style.get_box().display) {
|
||||||
Display::None => element.unset_pseudo_element_box(which),
|
Display::None => element.unset_pseudo_element_box(which),
|
||||||
Display::Contents => {
|
Display::Contents => {
|
||||||
element.unset_pseudo_element_box(which);
|
|
||||||
let items = generate_pseudo_element_content(&style, element, context);
|
let items = generate_pseudo_element_content(&style, element, context);
|
||||||
|
let box_slot = element.pseudo_element_box_slot(which);
|
||||||
|
box_slot.set(LayoutBox::DisplayContents);
|
||||||
traverse_pseudo_element_contents(element, &style, context, handler, items);
|
traverse_pseudo_element_contents(element, &style, context, handler, items);
|
||||||
},
|
},
|
||||||
Display::GeneratingBox(display) => {
|
Display::GeneratingBox(display) => {
|
||||||
let items = generate_pseudo_element_content(&style, element, context);
|
let items = generate_pseudo_element_content(&style, element, context);
|
||||||
let contents = Contents::OfPseudoElement(items);
|
|
||||||
let box_slot = element.pseudo_element_box_slot(which);
|
let box_slot = element.pseudo_element_box_slot(which);
|
||||||
|
let contents = Contents::OfPseudoElement(items);
|
||||||
handler.handle_element(element, &style, display, contents, box_slot);
|
handler.handle_element(element, &style, display, contents, box_slot);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
element.unset_pseudo_element_box(which)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +372,9 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode<'dom> + Send + Sync {
|
||||||
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
fn element_box_slot(&self) -> BoxSlot<'dom>;
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>;
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement);
|
||||||
fn unset_boxes_in_subtree(self);
|
|
||||||
|
/// Remove boxes for the element itself, and its `:before` and `:after` if any.
|
||||||
|
fn unset_all_boxes(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'dom, T> NodeExt<'dom> for T
|
impl<'dom, T> NodeExt<'dom> for T
|
||||||
|
@ -458,65 +459,29 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> {
|
||||||
let mut data = self.layout_data_mut();
|
let data = self.layout_data_mut();
|
||||||
let pseudos = data.pseudo_elements.get_or_insert_with(Default::default);
|
|
||||||
let cell = match which {
|
let cell = match which {
|
||||||
WhichPseudoElement::Before => &mut pseudos.before,
|
WhichPseudoElement::Before => &data.pseudo_before_box,
|
||||||
WhichPseudoElement::After => &mut pseudos.after,
|
WhichPseudoElement::After => &data.pseudo_after_box,
|
||||||
};
|
};
|
||||||
BoxSlot::new(cell.clone())
|
BoxSlot::new(cell.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
fn unset_pseudo_element_box(self, which: WhichPseudoElement) {
|
||||||
if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements {
|
let data = self.layout_data_mut();
|
||||||
match which {
|
let cell = match which {
|
||||||
WhichPseudoElement::Before => *pseudos.before.borrow_mut() = None,
|
WhichPseudoElement::Before => &data.pseudo_before_box,
|
||||||
WhichPseudoElement::After => *pseudos.after.borrow_mut() = None,
|
WhichPseudoElement::After => &data.pseudo_after_box,
|
||||||
}
|
};
|
||||||
}
|
*cell.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset_boxes_in_subtree(self) {
|
fn unset_all_boxes(self) {
|
||||||
assert!(self.is_element());
|
let mut data = self.layout_data_mut();
|
||||||
assert!(self.parent_node().is_some());
|
*data.self_box.borrow_mut() = None;
|
||||||
|
*data.pseudo_before_box.borrow_mut() = None;
|
||||||
let mut node = self;
|
*data.pseudo_after_box.borrow_mut() = None;
|
||||||
loop {
|
// Stylo already takes care of removing all layout data
|
||||||
if node.is_element() {
|
// for DOM descendants of elements with `display: none`.
|
||||||
let traverse_children = {
|
|
||||||
let mut layout_data = node.layout_data_mut();
|
|
||||||
layout_data.pseudo_elements = None;
|
|
||||||
let self_box = layout_data.self_box.borrow_mut().take();
|
|
||||||
self_box.is_some()
|
|
||||||
};
|
|
||||||
if traverse_children {
|
|
||||||
// Only descend into children if we removed a box.
|
|
||||||
// If there wasn’t one, then descendants don’t have boxes either.
|
|
||||||
if let Some(child) = node.first_child() {
|
|
||||||
node = child;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if node == self {
|
|
||||||
// If this is the root of the subtree and we aren't descending
|
|
||||||
// into our children return now.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut next_is_a_sibling_of = node;
|
|
||||||
node = loop {
|
|
||||||
if let Some(sibling) = next_is_a_sibling_of.next_sibling() {
|
|
||||||
break sibling;
|
|
||||||
} else {
|
|
||||||
next_is_a_sibling_of = node
|
|
||||||
.parent_node()
|
|
||||||
.expect("reached the root while traversing only a subtree");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if next_is_a_sibling_of == self {
|
|
||||||
// Don’t go outside the subtree.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,8 @@ use crate::flow::BlockLevelBox;
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LayoutDataForElement {
|
pub struct LayoutDataForElement {
|
||||||
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
|
pub(super) self_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
|
pub(super) pseudo_before_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
}
|
pub(super) pseudo_after_box: ArcRefCell<Option<LayoutBox>>,
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub(super) struct PseudoElementBoxes {
|
|
||||||
pub before: ArcRefCell<Option<LayoutBox>>,
|
|
||||||
pub after: ArcRefCell<Option<LayoutBox>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) enum LayoutBox {
|
pub(super) enum LayoutBox {
|
||||||
|
|
|
@ -88,7 +88,7 @@ fn construct_for_root_element<'dom>(
|
||||||
|
|
||||||
let display_inside = match Display::from(box_style.display) {
|
let display_inside = match Display::from(box_style.display) {
|
||||||
Display::None => {
|
Display::None => {
|
||||||
root_element.unset_boxes_in_subtree();
|
root_element.unset_all_boxes();
|
||||||
return (ContainsFloats::No, Vec::new());
|
return (ContainsFloats::No, Vec::new());
|
||||||
},
|
},
|
||||||
Display::Contents => {
|
Display::Contents => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue