Skip to content

Commit

Permalink
layout_2020: Tag fragments with their pseudo content type
Browse files Browse the repository at this point in the history
This will allow us to answer queries and properly handle animations in
the future for fragments generated for pseudo content.
  • Loading branch information
mrobinson committed Jun 6, 2020
1 parent 7df4655 commit 89855af
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 265 deletions.
10 changes: 5 additions & 5 deletions components/layout_2020/display_list/mod.rs
Expand Up @@ -4,7 +4,7 @@

use crate::context::LayoutContext;
use crate::display_list::conversions::ToWebRender;
use crate::fragments::{BoxFragment, Fragment, TextFragment};
use crate::fragments::{BoxFragment, Fragment, Tag, TextFragment};
use crate::geom::{PhysicalPoint, PhysicalRect};
use crate::replaced::IntrinsicSizes;
use crate::style_ext::ComputedValuesExt;
Expand Down Expand Up @@ -348,7 +348,7 @@ impl<'a> BuilderForBoxFragment<'a> {
}

fn build_background(&mut self, builder: &mut DisplayListBuilder) {
if self.fragment.tag == builder.element_for_canvas_background {
if self.fragment.tag.node() == builder.element_for_canvas_background {
// This background is already painted for the canvas, don’t paint it again here.
return;
}
Expand Down Expand Up @@ -405,7 +405,7 @@ impl<'a> BuilderForBoxFragment<'a> {
let (width, height, key) = match image_url.url() {
Some(url) => {
match builder.context.get_webrender_image_for_url(
self.fragment.tag,
self.fragment.tag.node(),
url.clone(),
UsePlaceholder::No,
) {
Expand Down Expand Up @@ -541,15 +541,15 @@ fn glyphs(
glyphs
}

fn hit_info(style: &ComputedValues, tag: OpaqueNode, auto_cursor: Cursor) -> HitInfo {
fn hit_info(style: &ComputedValues, tag: Tag, auto_cursor: Cursor) -> HitInfo {
use style::computed_values::pointer_events::T as PointerEvents;

let inherited_ui = style.get_inherited_ui();
if inherited_ui.pointer_events == PointerEvents::None {
None
} else {
let cursor = cursor(inherited_ui.cursor.keyword, auto_cursor);
Some((tag.0 as u64, cursor as u16))
Some((tag.node().0 as u64, cursor as u16))
}
}

Expand Down
13 changes: 5 additions & 8 deletions components/layout_2020/display_list/stacking_context.rs
Expand Up @@ -11,7 +11,6 @@ use crate::fragments::{
use crate::geom::PhysicalRect;
use crate::style_ext::ComputedValuesExt;
use euclid::default::Rect;
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
use servo_arc::Arc as ServoArc;
use std::cmp::Ordering;
use std::mem;
Expand Down Expand Up @@ -329,7 +328,7 @@ impl StackingContext {

// The `StackingContextFragment` we found is for the root DOM element:
debug_assert_eq!(
box_fragment.tag,
box_fragment.tag.node(),
fragment_tree.canvas_background.root_element
);

Expand Down Expand Up @@ -705,12 +704,10 @@ impl BoxFragment {
let overflow_y = self.style.get_box().overflow_y;
let original_scroll_and_clip_info = builder.current_space_and_clip;
if overflow_x != ComputedOverflow::Visible || overflow_y != ComputedOverflow::Visible {
// TODO(mrobinson): We should use the correct fragment type, once we generate
// fragments from ::before and ::after generated content selectors.
let id =
combine_id_with_fragment_type(self.tag.id() as usize, FragmentType::FragmentBody)
as u64;
let external_id = wr::ExternalScrollId(id, builder.wr.pipeline_id);
let external_id = wr::ExternalScrollId(
self.tag.to_display_list_fragment_id(),
builder.wr.pipeline_id,
);

let sensitivity = if ComputedOverflow::Hidden == overflow_x &&
ComputedOverflow::Hidden == overflow_y
Expand Down
90 changes: 62 additions & 28 deletions components/layout_2020/dom_traversal.rs
Expand Up @@ -27,11 +27,52 @@ use style::values::generics::counters::Content;
use style::values::generics::counters::ContentItem;

#[derive(Clone, Copy, Debug)]
pub enum WhichPseudoElement {
pub(crate) enum WhichPseudoElement {
Before,
After,
}

/// A data structure used to pass and store related layout information together to
/// avoid having to repeat the same arguments in argument lists.
#[derive(Clone)]
pub(crate) struct NodeAndStyleInfo<Node> {
pub node: Node,
pub pseudo_element_type: Option<WhichPseudoElement>,
pub style: ServoArc<ComputedValues>,
}

impl<Node> NodeAndStyleInfo<Node> {
fn new_with_pseudo(
node: Node,
pseudo_element_type: WhichPseudoElement,
style: ServoArc<ComputedValues>,
) -> Self {
Self {
node,
pseudo_element_type: Some(pseudo_element_type),
style,
}
}

pub(crate) fn new(node: Node, style: ServoArc<ComputedValues>) -> Self {
Self {
node,
pseudo_element_type: None,
style,
}
}
}

impl<Node: Clone> NodeAndStyleInfo<Node> {
pub(crate) fn new_replacing_style(&self, style: ServoArc<ComputedValues>) -> Self {
Self {
node: self.node.clone(),
pseudo_element_type: self.pseudo_element_type.clone(),
style,
}
}
}

pub(super) enum Contents {
/// Refers to a DOM subtree, plus `::before` and `::after` pseudo-elements.
OfElement,
Expand Down Expand Up @@ -60,18 +101,12 @@ pub(super) trait TraversalHandler<'dom, Node>
where
Node: 'dom,
{
fn handle_text(
&mut self,
node: Node,
text: Cow<'dom, str>,
parent_style: ServoArc<ComputedValues>,
);
fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>);

/// Or pseudo-element
fn handle_element(
&mut self,
node: Node,
style: ServoArc<ComputedValues>,
info: &NodeAndStyleInfo<Node>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
Expand All @@ -89,7 +124,8 @@ fn traverse_children_of<'dom, Node>(

for child in iter_child_nodes(parent_element) {
if let Some(contents) = child.as_text() {
handler.handle_text(child, contents, child.style(context));
let info = NodeAndStyleInfo::new(child, child.style(context));
handler.handle_text(&info, contents);
} else if child.is_element() {
traverse_element(child, context, handler);
}
Expand Down Expand Up @@ -122,7 +158,8 @@ fn traverse_element<'dom, Node>(
Display::GeneratingBox(display) => {
let contents = replaced.map_or(Contents::OfElement, Contents::Replaced);
let box_slot = element.element_box_slot();
handler.handle_element(element, style, display, contents, box_slot);
let info = NodeAndStyleInfo::new(element, style);
handler.handle_element(&info, display, contents, box_slot);
},
}
}
Expand All @@ -136,19 +173,20 @@ fn traverse_pseudo_element<'dom, Node>(
Node: NodeExt<'dom>,
{
if let Some(style) = pseudo_element_style(which, element, context) {
match Display::from(style.get_box().display) {
let info = NodeAndStyleInfo::new_with_pseudo(element, which, style);
match Display::from(info.style.get_box().display) {
Display::None => element.unset_pseudo_element_box(which),
Display::Contents => {
let items = generate_pseudo_element_content(&style, element, context);
let items = generate_pseudo_element_content(&info.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(&info, context, handler, items);
},
Display::GeneratingBox(display) => {
let items = generate_pseudo_element_content(&style, element, context);
let items = generate_pseudo_element_content(&info.style, element, context);
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(&info, display, contents, box_slot);
},
}
} else {
Expand All @@ -157,8 +195,7 @@ fn traverse_pseudo_element<'dom, Node>(
}

fn traverse_pseudo_element_contents<'dom, Node>(
node: Node,
pseudo_element_style: &ServoArc<ComputedValues>,
info: &NodeAndStyleInfo<Node>,
context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>,
items: Vec<PseudoElementContentItem>,
Expand All @@ -168,9 +205,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
let mut anonymous_style = None;
for item in items {
match item {
PseudoElementContentItem::Text(text) => {
handler.handle_text(node, text.into(), pseudo_element_style.clone())
},
PseudoElementContentItem::Text(text) => handler.handle_text(&info, text.into()),
PseudoElementContentItem::Replaced(contents) => {
let item_style = anonymous_style.get_or_insert_with(|| {
context
Expand All @@ -179,7 +214,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
.style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards,
&PseudoElement::ServoText,
&pseudo_element_style,
&info.style,
)
});
let display_inline = DisplayGeneratingBox::OutsideInside {
Expand All @@ -191,9 +226,9 @@ fn traverse_pseudo_element_contents<'dom, Node>(
Display::from(item_style.get_box().display) ==
Display::GeneratingBox(display_inline)
);
let info = info.new_replacing_style(item_style.clone());
handler.handle_element(
node,
item_style.clone(),
&info,
display_inline,
Contents::Replaced(contents),
// We don’t keep pointers to boxes generated by contents of pseudo-elements
Expand Down Expand Up @@ -239,16 +274,15 @@ impl NonReplacedContents {
pub(crate) fn traverse<'dom, Node>(
self,
context: &LayoutContext,
node: Node,
inherited_style: &ServoArc<ComputedValues>,
info: &NodeAndStyleInfo<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
match self {
NonReplacedContents::OfElement => traverse_children_of(node, context, handler),
NonReplacedContents::OfElement => traverse_children_of(info.node, context, handler),
NonReplacedContents::OfPseudoElement(items) => {
traverse_pseudo_element_contents(node, inherited_style, context, handler, items)
traverse_pseudo_element_contents(info, context, handler, items)
},
}
}
Expand Down

0 comments on commit 89855af

Please sign in to comment.