Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

layout_2020: Tag fragments with their pseudo content type #26805

Merged
merged 1 commit into from Jun 6, 2020
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

layout_2020: Tag fragments with their pseudo content type

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
commit 89855afa4daed56907b84daeb674066524e4352c
@@ -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;
@@ -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;
}
@@ -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,
) {
@@ -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))
}
}

@@ -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;
@@ -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
);

@@ -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
@@ -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,
@@ -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>,
@@ -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);
}
@@ -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);
},
}
}
@@ -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 {
@@ -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>,
@@ -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
@@ -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 {
@@ -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
@@ -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)
},
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.