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.
This commit is contained in:
Martin Robinson 2020-06-05 12:06:25 +02:00
parent 7df4655b60
commit 89855afa4d
14 changed files with 271 additions and 265 deletions

View file

@ -4,7 +4,7 @@
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::display_list::conversions::ToWebRender; 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::geom::{PhysicalPoint, PhysicalRect};
use crate::replaced::IntrinsicSizes; use crate::replaced::IntrinsicSizes;
use crate::style_ext::ComputedValuesExt; use crate::style_ext::ComputedValuesExt;
@ -348,7 +348,7 @@ impl<'a> BuilderForBoxFragment<'a> {
} }
fn build_background(&mut self, builder: &mut DisplayListBuilder) { 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, dont paint it again here. // This background is already painted for the canvas, dont paint it again here.
return; return;
} }
@ -405,7 +405,7 @@ impl<'a> BuilderForBoxFragment<'a> {
let (width, height, key) = match image_url.url() { let (width, height, key) = match image_url.url() {
Some(url) => { Some(url) => {
match builder.context.get_webrender_image_for_url( match builder.context.get_webrender_image_for_url(
self.fragment.tag, self.fragment.tag.node(),
url.clone(), url.clone(),
UsePlaceholder::No, UsePlaceholder::No,
) { ) {
@ -541,7 +541,7 @@ fn glyphs(
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; use style::computed_values::pointer_events::T as PointerEvents;
let inherited_ui = style.get_inherited_ui(); let inherited_ui = style.get_inherited_ui();
@ -549,7 +549,7 @@ fn hit_info(style: &ComputedValues, tag: OpaqueNode, auto_cursor: Cursor) -> Hit
None None
} else { } else {
let cursor = cursor(inherited_ui.cursor.keyword, auto_cursor); 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))
} }
} }

View file

@ -11,7 +11,6 @@ use crate::fragments::{
use crate::geom::PhysicalRect; use crate::geom::PhysicalRect;
use crate::style_ext::ComputedValuesExt; use crate::style_ext::ComputedValuesExt;
use euclid::default::Rect; use euclid::default::Rect;
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::mem; use std::mem;
@ -329,7 +328,7 @@ impl StackingContext {
// The `StackingContextFragment` we found is for the root DOM element: // The `StackingContextFragment` we found is for the root DOM element:
debug_assert_eq!( debug_assert_eq!(
box_fragment.tag, box_fragment.tag.node(),
fragment_tree.canvas_background.root_element fragment_tree.canvas_background.root_element
); );
@ -705,12 +704,10 @@ impl BoxFragment {
let overflow_y = self.style.get_box().overflow_y; let overflow_y = self.style.get_box().overflow_y;
let original_scroll_and_clip_info = builder.current_space_and_clip; let original_scroll_and_clip_info = builder.current_space_and_clip;
if overflow_x != ComputedOverflow::Visible || overflow_y != ComputedOverflow::Visible { if overflow_x != ComputedOverflow::Visible || overflow_y != ComputedOverflow::Visible {
// TODO(mrobinson): We should use the correct fragment type, once we generate let external_id = wr::ExternalScrollId(
// fragments from ::before and ::after generated content selectors. self.tag.to_display_list_fragment_id(),
let id = builder.wr.pipeline_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 sensitivity = if ComputedOverflow::Hidden == overflow_x && let sensitivity = if ComputedOverflow::Hidden == overflow_x &&
ComputedOverflow::Hidden == overflow_y ComputedOverflow::Hidden == overflow_y

View file

@ -27,11 +27,52 @@ use style::values::generics::counters::Content;
use style::values::generics::counters::ContentItem; use style::values::generics::counters::ContentItem;
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum WhichPseudoElement { pub(crate) enum WhichPseudoElement {
Before, Before,
After, 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 { pub(super) enum Contents {
/// Refers to a DOM subtree, plus `::before` and `::after` pseudo-elements. /// Refers to a DOM subtree, plus `::before` and `::after` pseudo-elements.
OfElement, OfElement,
@ -60,18 +101,12 @@ pub(super) trait TraversalHandler<'dom, Node>
where where
Node: 'dom, Node: 'dom,
{ {
fn handle_text( fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>);
&mut self,
node: Node,
text: Cow<'dom, str>,
parent_style: ServoArc<ComputedValues>,
);
/// Or pseudo-element /// Or pseudo-element
fn handle_element( fn handle_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: ServoArc<ComputedValues>,
display: DisplayGeneratingBox, display: DisplayGeneratingBox,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -89,7 +124,8 @@ fn traverse_children_of<'dom, Node>(
for child in iter_child_nodes(parent_element) { for child in iter_child_nodes(parent_element) {
if let Some(contents) = child.as_text() { 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() { } else if child.is_element() {
traverse_element(child, context, handler); traverse_element(child, context, handler);
} }
@ -122,7 +158,8 @@ fn traverse_element<'dom, Node>(
Display::GeneratingBox(display) => { Display::GeneratingBox(display) => {
let contents = replaced.map_or(Contents::OfElement, Contents::Replaced); let contents = replaced.map_or(Contents::OfElement, Contents::Replaced);
let box_slot = element.element_box_slot(); 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>, Node: NodeExt<'dom>,
{ {
if let Some(style) = pseudo_element_style(which, element, context) { 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::None => element.unset_pseudo_element_box(which),
Display::Contents => { 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); let box_slot = element.pseudo_element_box_slot(which);
box_slot.set(LayoutBox::DisplayContents); 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) => { 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 box_slot = element.pseudo_element_box_slot(which);
let contents = Contents::OfPseudoElement(items); let contents = Contents::OfPseudoElement(items);
handler.handle_element(element, style, display, contents, box_slot); handler.handle_element(&info, display, contents, box_slot);
}, },
} }
} else { } else {
@ -157,8 +195,7 @@ fn traverse_pseudo_element<'dom, Node>(
} }
fn traverse_pseudo_element_contents<'dom, Node>( fn traverse_pseudo_element_contents<'dom, Node>(
node: Node, info: &NodeAndStyleInfo<Node>,
pseudo_element_style: &ServoArc<ComputedValues>,
context: &LayoutContext, context: &LayoutContext,
handler: &mut impl TraversalHandler<'dom, Node>, handler: &mut impl TraversalHandler<'dom, Node>,
items: Vec<PseudoElementContentItem>, items: Vec<PseudoElementContentItem>,
@ -168,9 +205,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
let mut anonymous_style = None; let mut anonymous_style = None;
for item in items { for item in items {
match item { match item {
PseudoElementContentItem::Text(text) => { PseudoElementContentItem::Text(text) => handler.handle_text(&info, text.into()),
handler.handle_text(node, text.into(), pseudo_element_style.clone())
},
PseudoElementContentItem::Replaced(contents) => { PseudoElementContentItem::Replaced(contents) => {
let item_style = anonymous_style.get_or_insert_with(|| { let item_style = anonymous_style.get_or_insert_with(|| {
context context
@ -179,7 +214,7 @@ fn traverse_pseudo_element_contents<'dom, Node>(
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards, &context.shared_context().guards,
&PseudoElement::ServoText, &PseudoElement::ServoText,
&pseudo_element_style, &info.style,
) )
}); });
let display_inline = DisplayGeneratingBox::OutsideInside { let display_inline = DisplayGeneratingBox::OutsideInside {
@ -191,9 +226,9 @@ fn traverse_pseudo_element_contents<'dom, Node>(
Display::from(item_style.get_box().display) == Display::from(item_style.get_box().display) ==
Display::GeneratingBox(display_inline) Display::GeneratingBox(display_inline)
); );
let info = info.new_replacing_style(item_style.clone());
handler.handle_element( handler.handle_element(
node, &info,
item_style.clone(),
display_inline, display_inline,
Contents::Replaced(contents), Contents::Replaced(contents),
// We dont keep pointers to boxes generated by contents of pseudo-elements // We dont keep pointers to boxes generated by contents of pseudo-elements
@ -239,16 +274,15 @@ impl NonReplacedContents {
pub(crate) fn traverse<'dom, Node>( pub(crate) fn traverse<'dom, Node>(
self, self,
context: &LayoutContext, context: &LayoutContext,
node: Node, info: &NodeAndStyleInfo<Node>,
inherited_style: &ServoArc<ComputedValues>,
handler: &mut impl TraversalHandler<'dom, Node>, handler: &mut impl TraversalHandler<'dom, Node>,
) where ) where
Node: NodeExt<'dom>, Node: NodeExt<'dom>,
{ {
match self { match self {
NonReplacedContents::OfElement => traverse_children_of(node, context, handler), NonReplacedContents::OfElement => traverse_children_of(info.node, context, handler),
NonReplacedContents::OfPseudoElement(items) => { NonReplacedContents::OfPseudoElement(items) => {
traverse_pseudo_element_contents(node, inherited_style, context, handler, items) traverse_pseudo_element_contents(info, context, handler, items)
}, },
} }
} }

View file

@ -4,9 +4,12 @@
use crate::cell::ArcRefCell; use crate::cell::ArcRefCell;
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{BoxSlot, Contents, NodeExt, NonReplacedContents, TraversalHandler}; use crate::dom_traversal::{
BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler,
};
use crate::element_data::LayoutBox; use crate::element_data::LayoutBox;
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout}; use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
use crate::fragments::Tag;
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayGeneratingBox; use crate::style_ext::DisplayGeneratingBox;
@ -14,7 +17,6 @@ use crate::ContainingBlock;
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use servo_arc::Arc; use servo_arc::Arc;
use std::borrow::Cow; use std::borrow::Cow;
use style::properties::ComputedValues;
use style::values::computed::Length; use style::values::computed::Length;
use style::values::specified::text::TextDecorationLine; use style::values::specified::text::TextDecorationLine;
use style::Zero; use style::Zero;
@ -35,24 +37,22 @@ pub(crate) enum FlexLevelBox {
impl FlexContainer { impl FlexContainer {
pub fn construct<'dom>( pub fn construct<'dom>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
style: &Arc<ComputedValues>,
contents: NonReplacedContents, contents: NonReplacedContents,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
propagated_text_decoration_line: TextDecorationLine, propagated_text_decoration_line: TextDecorationLine,
) -> (Self, BoxContentSizes) { ) -> (Self, BoxContentSizes) {
let text_decoration_line = let text_decoration_line =
propagated_text_decoration_line | style.clone_text_decoration_line(); propagated_text_decoration_line | info.style.clone_text_decoration_line();
let mut builder = FlexContainerBuilder { let mut builder = FlexContainerBuilder {
context, context,
node, info,
style,
text_decoration_line, text_decoration_line,
contiguous_text_runs: Vec::new(), contiguous_text_runs: Vec::new(),
jobs: Vec::new(), jobs: Vec::new(),
has_text_runs: false, has_text_runs: false,
}; };
contents.traverse(context, node, style, &mut builder); contents.traverse(context, info, &mut builder);
let content_sizes = content_sizes.compute(|| { let content_sizes = content_sizes.compute(|| {
// FIXME // FIXME
ContentSizes::zero() ContentSizes::zero()
@ -64,8 +64,7 @@ impl FlexContainer {
/// https://drafts.csswg.org/css-flexbox/#flex-items /// https://drafts.csswg.org/css-flexbox/#flex-items
struct FlexContainerBuilder<'a, 'dom, Node> { struct FlexContainerBuilder<'a, 'dom, Node> {
context: &'a LayoutContext<'a>, context: &'a LayoutContext<'a>,
node: Node, info: &'a NodeAndStyleInfo<Node>,
style: &'a Arc<ComputedValues>,
text_decoration_line: TextDecorationLine, text_decoration_line: TextDecorationLine,
contiguous_text_runs: Vec<TextRun<'dom, Node>>, contiguous_text_runs: Vec<TextRun<'dom, Node>>,
/// To be run in parallel with rayon in `finish` /// To be run in parallel with rayon in `finish`
@ -76,8 +75,7 @@ struct FlexContainerBuilder<'a, 'dom, Node> {
enum FlexLevelJob<'dom, Node> { enum FlexLevelJob<'dom, Node> {
/// Or pseudo-element /// Or pseudo-element
Element { Element {
node: Node, info: NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display: DisplayGeneratingBox, display: DisplayGeneratingBox,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -86,28 +84,25 @@ enum FlexLevelJob<'dom, Node> {
} }
struct TextRun<'dom, Node> { struct TextRun<'dom, Node> {
node: Node, info: NodeAndStyleInfo<Node>,
text: Cow<'dom, str>, text: Cow<'dom, str>,
parent_style: Arc<ComputedValues>,
} }
impl<'a, 'dom, Node: 'dom> TraversalHandler<'dom, Node> for FlexContainerBuilder<'a, 'dom, Node> impl<'a, 'dom, Node: 'dom> TraversalHandler<'dom, Node> for FlexContainerBuilder<'a, 'dom, Node>
where where
Node: NodeExt<'dom>, Node: NodeExt<'dom>,
{ {
fn handle_text(&mut self, node: Node, text: Cow<'dom, str>, parent_style: Arc<ComputedValues>) { fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, text: Cow<'dom, str>) {
self.contiguous_text_runs.push(TextRun { self.contiguous_text_runs.push(TextRun {
node, info: info.clone(),
text, text,
parent_style,
}) })
} }
/// Or pseudo-element /// Or pseudo-element
fn handle_element( fn handle_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display: DisplayGeneratingBox, display: DisplayGeneratingBox,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -118,8 +113,7 @@ where
self.wrap_any_text_in_anonymous_block_container(); self.wrap_any_text_in_anonymous_block_container();
self.jobs.push(FlexLevelJob::Element { self.jobs.push(FlexLevelJob::Element {
node, info: info.clone(),
style,
display, display,
contents, contents,
box_slot, box_slot,
@ -162,7 +156,7 @@ where
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&self.context.shared_context().guards, &self.context.shared_context().guards,
&style::selector_parser::PseudoElement::ServoText, &style::selector_parser::PseudoElement::ServoText,
self.style, &self.info.style,
), ),
) )
} else { } else {
@ -175,20 +169,20 @@ where
FlexLevelJob::TextRuns(runs) => ArcRefCell::new(FlexLevelBox::FlexItem( FlexLevelJob::TextRuns(runs) => ArcRefCell::new(FlexLevelBox::FlexItem(
IndependentFormattingContext::construct_for_text_runs( IndependentFormattingContext::construct_for_text_runs(
self.context, self.context,
self.node, &self
anonymous_style.clone().unwrap(), .info
.new_replacing_style(anonymous_style.clone().unwrap()),
runs.into_iter().map(|run| crate::flow::inline::TextRun { runs.into_iter().map(|run| crate::flow::inline::TextRun {
tag: run.node.as_opaque(), tag: Tag::from_node_and_style_info(&run.info),
text: run.text.into(), text: run.text.into(),
parent_style: run.parent_style, parent_style: run.info.style,
}), }),
ContentSizesRequest::None, // FIXME: request sizes when we start using them ContentSizesRequest::None, // FIXME: request sizes when we start using them
self.text_decoration_line, self.text_decoration_line,
), ),
)), )),
FlexLevelJob::Element { FlexLevelJob::Element {
node, info,
style,
display, display,
contents, contents,
box_slot, box_slot,
@ -196,13 +190,12 @@ where
let display_inside = match display { let display_inside = match display {
DisplayGeneratingBox::OutsideInside { inside, .. } => inside, DisplayGeneratingBox::OutsideInside { inside, .. } => inside,
}; };
let box_ = if style.get_box().position.is_absolutely_positioned() { let box_ = if info.style.get_box().position.is_absolutely_positioned() {
// https://drafts.csswg.org/css-flexbox/#abspos-items // https://drafts.csswg.org/css-flexbox/#abspos-items
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct( AbsolutelyPositionedBox::construct(
self.context, self.context,
node, &info,
style.clone(),
display_inside, display_inside,
contents, contents,
), ),
@ -211,8 +204,7 @@ where
ArcRefCell::new(FlexLevelBox::FlexItem( ArcRefCell::new(FlexLevelBox::FlexItem(
IndependentFormattingContext::construct( IndependentFormattingContext::construct(
self.context, self.context,
node, &info,
style.clone(),
display_inside, display_inside,
contents, contents,
ContentSizesRequest::None, // FIXME: request sizes when we start using them ContentSizesRequest::None, // FIXME: request sizes when we start using them

View file

@ -4,12 +4,15 @@
use crate::cell::ArcRefCell; use crate::cell::ArcRefCell;
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{BoxSlot, Contents, NodeExt, NonReplacedContents, TraversalHandler}; use crate::dom_traversal::{
BoxSlot, Contents, NodeAndStyleInfo, NodeExt, NonReplacedContents, TraversalHandler,
};
use crate::element_data::LayoutBox; use crate::element_data::LayoutBox;
use crate::flow::float::FloatBox; use crate::flow::float::FloatBox;
use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun}; use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun};
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::Tag;
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::AbsolutelyPositionedBox;
use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside}; use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside};
@ -23,18 +26,19 @@ use style::selector_parser::PseudoElement;
use style::values::specified::text::TextDecorationLine; use style::values::specified::text::TextDecorationLine;
impl BlockFormattingContext { impl BlockFormattingContext {
pub fn construct<'dom>( pub fn construct<'dom, Node>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<Node>,
style: &Arc<ComputedValues>,
contents: NonReplacedContents, contents: NonReplacedContents,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
propagated_text_decoration_line: TextDecorationLine, propagated_text_decoration_line: TextDecorationLine,
) -> (Self, BoxContentSizes) { ) -> (Self, BoxContentSizes)
where
Node: NodeExt<'dom>,
{
let (contents, contains_floats, inline_content_sizes) = BlockContainer::construct( let (contents, contains_floats, inline_content_sizes) = BlockContainer::construct(
context, context,
node, info,
style,
contents, contents,
content_sizes, content_sizes,
propagated_text_decoration_line, propagated_text_decoration_line,
@ -74,9 +78,8 @@ impl BlockFormattingContext {
} }
struct BlockLevelJob<'dom, Node> { struct BlockLevelJob<'dom, Node> {
node: Node, info: NodeAndStyleInfo<Node>,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
style: Arc<ComputedValues>,
kind: BlockLevelCreator, kind: BlockLevelCreator,
} }
@ -116,9 +119,9 @@ enum IntermediateBlockContainer {
struct BlockContainerBuilder<'dom, 'style, Node> { struct BlockContainerBuilder<'dom, 'style, Node> {
context: &'style LayoutContext<'style>, context: &'style LayoutContext<'style>,
root: Node, /// This NodeAndStyleInfo contains the root node, the corresponding pseudo
/// content designator, and the block container style.
block_container_style: &'style Arc<ComputedValues>, info: &'style NodeAndStyleInfo<Node>,
/// The list of block-level boxes to be built for the final block container. /// The list of block-level boxes to be built for the final block container.
/// ///
@ -168,20 +171,21 @@ struct BlockContainerBuilder<'dom, 'style, Node> {
} }
impl BlockContainer { impl BlockContainer {
pub fn construct<'dom>( pub fn construct<'dom, Node>(
context: &LayoutContext, context: &LayoutContext,
root: impl NodeExt<'dom>, info: &NodeAndStyleInfo<Node>,
block_container_style: &Arc<ComputedValues>,
contents: NonReplacedContents, contents: NonReplacedContents,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
propagated_text_decoration_line: TextDecorationLine, propagated_text_decoration_line: TextDecorationLine,
) -> (BlockContainer, ContainsFloats, BoxContentSizes) { ) -> (BlockContainer, ContainsFloats, BoxContentSizes)
where
Node: NodeExt<'dom>,
{
let text_decoration_line = let text_decoration_line =
propagated_text_decoration_line | block_container_style.clone_text_decoration_line(); propagated_text_decoration_line | info.style.clone_text_decoration_line();
let mut builder = BlockContainerBuilder { let mut builder = BlockContainerBuilder {
context, context,
root, info,
block_container_style,
block_level_boxes: Vec::new(), block_level_boxes: Vec::new(),
ongoing_inline_formatting_context: InlineFormattingContext::new(text_decoration_line), ongoing_inline_formatting_context: InlineFormattingContext::new(text_decoration_line),
ongoing_inline_boxes_stack: Vec::new(), ongoing_inline_boxes_stack: Vec::new(),
@ -189,7 +193,7 @@ impl BlockContainer {
contains_floats: ContainsFloats::No, contains_floats: ContainsFloats::No,
}; };
contents.traverse(context, root, block_container_style, &mut builder); contents.traverse(context, info, &mut builder);
debug_assert!(builder.ongoing_inline_boxes_stack.is_empty()); debug_assert!(builder.ongoing_inline_boxes_stack.is_empty());
@ -272,8 +276,7 @@ where
{ {
fn handle_element( fn handle_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display: DisplayGeneratingBox, display: DisplayGeneratingBox,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -281,32 +284,25 @@ where
match display { match display {
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside { DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
DisplayOutside::Inline => box_slot.set(LayoutBox::InlineLevel( DisplayOutside::Inline => box_slot.set(LayoutBox::InlineLevel(
self.handle_inline_level_element(node, style, inside, contents), self.handle_inline_level_element(info, inside, contents),
)), )),
DisplayOutside::Block => { DisplayOutside::Block => {
let box_style = style.get_box(); let box_style = info.style.get_box();
// Floats and abspos cause blockification, so they only happen in this case. // Floats and abspos cause blockification, so they only happen in this case.
// https://drafts.csswg.org/css2/visuren.html#dis-pos-flo // https://drafts.csswg.org/css2/visuren.html#dis-pos-flo
if box_style.position.is_absolutely_positioned() { if box_style.position.is_absolutely_positioned() {
self.handle_absolutely_positioned_element( self.handle_absolutely_positioned_element(info, inside, contents, box_slot)
node, style, inside, contents, box_slot,
)
} else if box_style.float.is_floating() { } else if box_style.float.is_floating() {
self.handle_float_element(node, style, inside, contents, box_slot) self.handle_float_element(info, inside, contents, box_slot)
} else { } else {
self.handle_block_level_element(node, style, inside, contents, box_slot) self.handle_block_level_element(info, inside, contents, box_slot)
} }
}, },
}, },
} }
} }
fn handle_text( fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, input: Cow<'dom, str>) {
&mut self,
node: Node,
input: Cow<'dom, str>,
parent_style: Arc<ComputedValues>,
) {
let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input); let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input);
if leading_whitespace || !input.is_empty() { if leading_whitespace || !input.is_empty() {
// This text node should be pushed either to the next ongoing // This text node should be pushed either to the next ongoing
@ -356,8 +352,8 @@ where
if let Some(text) = new_text_run_contents { if let Some(text) = new_text_run_contents {
inlines.push(ArcRefCell::new(InlineLevelBox::TextRun(TextRun { inlines.push(ArcRefCell::new(InlineLevelBox::TextRun(TextRun {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
parent_style, parent_style: Arc::clone(&info.style),
text, text,
}))) })))
} }
@ -430,30 +426,27 @@ where
fn handle_inline_level_element( fn handle_inline_level_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
) -> ArcRefCell<InlineLevelBox> { ) -> ArcRefCell<InlineLevelBox> {
let style = &info.style;
let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() { let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() {
// We found un inline box. // We found un inline box.
// Whatever happened before, all we need to do before recurring // Whatever happened before, all we need to do before recurring
// is to remember this ongoing inline level box. // is to remember this ongoing inline level box.
self.ongoing_inline_boxes_stack.push(InlineBox { self.ongoing_inline_boxes_stack.push(InlineBox {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
style: style.clone(), style: info.style.clone(),
first_fragment: true, first_fragment: true,
last_fragment: false, last_fragment: false,
children: vec![], children: vec![],
}); });
// `unwrap` doesnt panic here because `is_replaced` returned `false`. // `unwrap` doesnt panic here because `is_replaced` returned `false`.
NonReplacedContents::try_from(contents).unwrap().traverse( NonReplacedContents::try_from(contents)
self.context, .unwrap()
node, .traverse(self.context, info, self);
&style,
self,
);
let mut inline_box = self let mut inline_box = self
.ongoing_inline_boxes_stack .ongoing_inline_boxes_stack
@ -466,8 +459,7 @@ where
ArcRefCell::new(InlineLevelBox::Atomic( ArcRefCell::new(InlineLevelBox::Atomic(
IndependentFormattingContext::construct( IndependentFormattingContext::construct(
self.context, self.context,
node, info,
style,
display_inside, display_inside,
contents, contents,
content_sizes, content_sizes,
@ -482,8 +474,7 @@ where
fn handle_block_level_element( fn handle_block_level_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -556,17 +547,15 @@ where
}, },
}; };
self.block_level_boxes.push(BlockLevelJob { self.block_level_boxes.push(BlockLevelJob {
node, info: info.clone(),
box_slot, box_slot,
style,
kind, kind,
}); });
} }
fn handle_absolutely_positioned_element( fn handle_absolutely_positioned_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -577,20 +566,13 @@ where
display_inside, display_inside,
}; };
self.block_level_boxes.push(BlockLevelJob { self.block_level_boxes.push(BlockLevelJob {
node, info: info.clone(),
box_slot, box_slot,
style,
kind, kind,
}); });
} else { } else {
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct( AbsolutelyPositionedBox::construct(self.context, info, display_inside, contents),
self.context,
node,
style,
display_inside,
contents,
),
))); )));
self.current_inline_level_boxes().push(box_.clone()); self.current_inline_level_boxes().push(box_.clone());
box_slot.set(LayoutBox::InlineLevel(box_)) box_slot.set(LayoutBox::InlineLevel(box_))
@ -599,8 +581,7 @@ where
fn handle_float_element( fn handle_float_element(
&mut self, &mut self,
node: Node, info: &NodeAndStyleInfo<Node>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
box_slot: BoxSlot<'dom>, box_slot: BoxSlot<'dom>,
@ -613,16 +594,14 @@ where
display_inside, display_inside,
}; };
self.block_level_boxes.push(BlockLevelJob { self.block_level_boxes.push(BlockLevelJob {
node, info: info.clone(),
box_slot, box_slot,
style,
kind, kind,
}); });
} else { } else {
let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct( let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct(
self.context, self.context,
node, info,
style,
display_inside, display_inside,
contents, contents,
))); )));
@ -642,7 +621,7 @@ where
} }
let context = self.context; let context = self.context;
let block_container_style = self.block_container_style; let block_container_style = &self.info.style;
let anonymous_style = self.anonymous_style.get_or_insert_with(|| { let anonymous_style = self.anonymous_style.get_or_insert_with(|| {
context context
.shared_context() .shared_context()
@ -650,7 +629,7 @@ where
.style_for_anonymous::<Node::ConcreteElement>( .style_for_anonymous::<Node::ConcreteElement>(
&context.shared_context().guards, &context.shared_context().guards,
&PseudoElement::ServoText, &PseudoElement::ServoText,
&block_container_style, block_container_style,
) )
}); });
@ -659,11 +638,11 @@ where
&mut self.ongoing_inline_formatting_context, &mut self.ongoing_inline_formatting_context,
)), )),
); );
let info = self.info.new_replacing_style(anonymous_style.clone());
self.block_level_boxes.push(BlockLevelJob { self.block_level_boxes.push(BlockLevelJob {
node: self.root, info,
// FIXME(nox): We should be storing this somewhere. // FIXME(nox): We should be storing this somewhere.
box_slot: BoxSlot::dummy(), box_slot: BoxSlot::dummy(),
style: anonymous_style.clone(),
kind, kind,
}); });
} }
@ -693,26 +672,24 @@ where
context: &LayoutContext, context: &LayoutContext,
max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>, max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>,
) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) { ) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) {
let node = self.node; let info = &self.info;
let style = self.style;
let (block_level_box, contains_floats) = match self.kind { let (block_level_box, contains_floats) = match self.kind {
BlockLevelCreator::SameFormattingContextBlock(contents) => { BlockLevelCreator::SameFormattingContextBlock(contents) => {
let (contents, contains_floats, box_content_sizes) = contents.finish( let (contents, contains_floats, box_content_sizes) = contents.finish(
context, context,
node, info,
&style,
ContentSizesRequest::inline_if( ContentSizesRequest::inline_if(
max_assign_in_flow_outer_content_sizes_to.is_some() && max_assign_in_flow_outer_content_sizes_to.is_some() &&
!style.inline_size_is_length(), !info.style.inline_size_is_length(),
), ),
); );
if let Some(to) = max_assign_in_flow_outer_content_sizes_to { if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
to.max_assign(&box_content_sizes.outer_inline(&style)) to.max_assign(&box_content_sizes.outer_inline(&info.style))
} }
let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock { let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
contents, contents,
style, style: Arc::clone(&info.style),
}); });
(block_level_box, contains_floats) (block_level_box, contains_floats)
}, },
@ -723,12 +700,11 @@ where
} => { } => {
let content_sizes = ContentSizesRequest::inline_if( let content_sizes = ContentSizesRequest::inline_if(
max_assign_in_flow_outer_content_sizes_to.is_some() && max_assign_in_flow_outer_content_sizes_to.is_some() &&
!style.inline_size_is_length(), !info.style.inline_size_is_length(),
); );
let contents = IndependentFormattingContext::construct( let contents = IndependentFormattingContext::construct(
context, context,
node, info,
style,
display_inside, display_inside,
contents, contents,
content_sizes, content_sizes,
@ -748,13 +724,7 @@ where
} => { } => {
let block_level_box = let block_level_box =
ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct( AbsolutelyPositionedBox::construct(context, info, display_inside, contents),
context,
node,
style,
display_inside,
contents,
),
))); )));
(block_level_box, ContainsFloats::No) (block_level_box, ContainsFloats::No)
}, },
@ -763,7 +733,7 @@ where
contents, contents,
} => { } => {
let block_level_box = ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox( let block_level_box = ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox(
FloatBox::construct(context, node, style, display_inside, contents), FloatBox::construct(context, info, display_inside, contents),
)); ));
(block_level_box, ContainsFloats::Yes) (block_level_box, ContainsFloats::Yes)
}, },
@ -775,19 +745,20 @@ where
} }
impl IntermediateBlockContainer { impl IntermediateBlockContainer {
fn finish<'dom>( fn finish<'dom, Node>(
self, self,
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<Node>,
style: &Arc<ComputedValues>,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
) -> (BlockContainer, ContainsFloats, BoxContentSizes) { ) -> (BlockContainer, ContainsFloats, BoxContentSizes)
where
Node: NodeExt<'dom>,
{
match self { match self {
IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => { IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => {
BlockContainer::construct( BlockContainer::construct(
context, context,
node, info,
style,
contents, contents,
content_sizes, content_sizes,
propagated_text_decoration_line, propagated_text_decoration_line,

View file

@ -3,12 +3,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::sizing::ContentSizesRequest; use crate::sizing::ContentSizesRequest;
use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::style_ext::{ComputedValuesExt, DisplayInside};
use servo_arc::Arc;
use style::properties::ComputedValues;
use style::values::specified::text::TextDecorationLine; use style::values::specified::text::TextDecorationLine;
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
@ -30,17 +28,15 @@ impl FloatContext {
impl FloatBox { impl FloatBox {
pub fn construct<'dom>( pub fn construct<'dom>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
) -> Self { ) -> Self {
let content_sizes = ContentSizesRequest::inline_if(!style.inline_size_is_length()); let content_sizes = ContentSizesRequest::inline_if(!info.style.inline_size_is_length());
Self { Self {
contents: IndependentFormattingContext::construct( contents: IndependentFormattingContext::construct(
context, context,
node, info,
style,
display_inside, display_inside,
contents, contents,
content_sizes, content_sizes,

View file

@ -9,7 +9,7 @@ use crate::flow::FlowLayout;
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::{ use crate::fragments::{
AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins, AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins,
DebugId, FontMetrics, Fragment, TextFragment, DebugId, FontMetrics, Fragment, Tag, TextFragment,
}; };
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{ use crate::positioned::{
@ -22,7 +22,6 @@ use crate::ContainingBlock;
use app_units::Au; use app_units::Au;
use gfx::text::text_run::GlyphRun; use gfx::text::text_run::GlyphRun;
use servo_arc::Arc; use servo_arc::Arc;
use style::dom::OpaqueNode;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::{Length, LengthPercentage, Percentage}; use style::values::computed::{Length, LengthPercentage, Percentage};
use style::values::specified::text::TextAlignKeyword; use style::values::specified::text::TextAlignKeyword;
@ -47,7 +46,7 @@ pub(crate) enum InlineLevelBox {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct InlineBox { pub(crate) struct InlineBox {
pub tag: OpaqueNode, pub tag: Tag,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub style: Arc<ComputedValues>, pub style: Arc<ComputedValues>,
pub first_fragment: bool, pub first_fragment: bool,
@ -58,7 +57,7 @@ pub(crate) struct InlineBox {
/// https://www.w3.org/TR/css-display-3/#css-text-run /// https://www.w3.org/TR/css-display-3/#css-text-run
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct TextRun { pub(crate) struct TextRun {
pub tag: OpaqueNode, pub tag: Tag,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub parent_style: Arc<ComputedValues>, pub parent_style: Arc<ComputedValues>,
pub text: String, pub text: String,
@ -78,7 +77,7 @@ struct InlineNestingLevelState<'box_tree> {
} }
struct PartialInlineBoxFragment<'box_tree> { struct PartialInlineBoxFragment<'box_tree> {
tag: OpaqueNode, tag: Tag,
style: Arc<ComputedValues>, style: Arc<ComputedValues>,
start_corner: Vec2<Length>, start_corner: Vec2<Length>,
padding: Sides<Length>, padding: Sides<Length>,

View file

@ -9,8 +9,10 @@ use crate::context::LayoutContext;
use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::float::{FloatBox, FloatContext};
use crate::flow::inline::InlineFormattingContext; use crate::flow::inline::InlineFormattingContext;
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout, NonReplacedIFC}; use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout, NonReplacedIFC};
use crate::fragments::{AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment}; use crate::fragments::{
use crate::fragments::{CollapsedBlockMargins, CollapsedMargin, Fragment}; AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins,
CollapsedMargin, Fragment, Tag,
};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
@ -19,7 +21,6 @@ use crate::ContainingBlock;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use rayon_croissant::ParallelIteratorExt; use rayon_croissant::ParallelIteratorExt;
use servo_arc::Arc; use servo_arc::Arc;
use style::dom::OpaqueNode;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::{Length, LengthOrAuto}; use style::values::computed::{Length, LengthOrAuto};
use style::Zero; use style::Zero;
@ -46,7 +47,7 @@ pub(crate) enum BlockContainer {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) enum BlockLevelBox { pub(crate) enum BlockLevelBox {
SameFormattingContextBlock { SameFormattingContextBlock {
tag: OpaqueNode, tag: Tag,
#[serde(skip_serializing)] #[serde(skip_serializing)]
style: Arc<ComputedValues>, style: Arc<ComputedValues>,
contents: BlockContainer, contents: BlockContainer,
@ -345,7 +346,7 @@ fn layout_in_flow_non_replaced_block_level(
layout_context: &LayoutContext, layout_context: &LayoutContext,
positioning_context: &mut PositioningContext, positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tag: OpaqueNode, tag: Tag,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
block_level_kind: NonReplacedContents, block_level_kind: NonReplacedContents,
tree_rank: usize, tree_rank: usize,
@ -500,7 +501,7 @@ fn layout_in_flow_non_replaced_block_level(
/// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height /// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height
fn layout_in_flow_replaced_block_level<'a>( fn layout_in_flow_replaced_block_level<'a>(
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tag: OpaqueNode, tag: Tag,
style: &Arc<ComputedValues>, style: &Arc<ComputedValues>,
replaced: &ReplacedContent, replaced: &ReplacedContent,
) -> BoxFragment { ) -> BoxFragment {

View file

@ -8,7 +8,7 @@ use crate::display_list::stacking_context::{
ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode, ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode,
StackingContextBuilder, StackingContextBuilder,
}; };
use crate::dom_traversal::{iter_child_nodes, Contents, NodeExt}; use crate::dom_traversal::{iter_child_nodes, Contents, NodeAndStyleInfo, NodeExt};
use crate::element_data::LayoutBox; use crate::element_data::LayoutBox;
use crate::flexbox::FlexLevelBox; use crate::flexbox::FlexLevelBox;
use crate::flow::construct::ContainsFloats; use crate::flow::construct::ContainsFloats;
@ -16,7 +16,7 @@ use crate::flow::float::FloatBox;
use crate::flow::inline::InlineLevelBox; use crate::flow::inline::InlineLevelBox;
use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::Fragment; use crate::fragments::{Fragment, Tag};
use crate::geom::flow_relative::Vec2; use crate::geom::flow_relative::Vec2;
use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSize}; use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSize};
use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::AbsolutelyPositionedBox;
@ -206,14 +206,10 @@ impl BoxTree {
if let Some((primary_style, display_inside, update_point)) = update_point(dirty_node) { if let Some((primary_style, display_inside, update_point)) = update_point(dirty_node) {
let contents = ReplacedContent::for_element(dirty_node) let contents = ReplacedContent::for_element(dirty_node)
.map_or(Contents::OfElement, Contents::Replaced); .map_or(Contents::OfElement, Contents::Replaced);
let out_of_flow_absolutely_positioned_box = let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style));
Arc::new(AbsolutelyPositionedBox::construct( let out_of_flow_absolutely_positioned_box = Arc::new(
context, AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
dirty_node, );
primary_style,
display_inside,
contents,
));
match update_point { match update_point {
UpdatePoint::AbsolutelyPositionedBlockLevelBox(block_level_box) => { UpdatePoint::AbsolutelyPositionedBlockLevelBox(block_level_box) => {
*block_level_box.borrow_mut() = *block_level_box.borrow_mut() =
@ -248,8 +244,8 @@ fn construct_for_root_element<'dom>(
context: &LayoutContext, context: &LayoutContext,
root_element: impl NodeExt<'dom>, root_element: impl NodeExt<'dom>,
) -> (ContainsFloats, Vec<ArcRefCell<BlockLevelBox>>) { ) -> (ContainsFloats, Vec<ArcRefCell<BlockLevelBox>>) {
let style = root_element.style(context); let info = NodeAndStyleInfo::new(root_element, root_element.style(context));
let box_style = style.get_box(); let box_style = info.style.get_box();
let display_inside = match Display::from(box_style.display) { let display_inside = match Display::from(box_style.display) {
Display::None => { Display::None => {
@ -272,13 +268,7 @@ fn construct_for_root_element<'dom>(
( (
ContainsFloats::No, ContainsFloats::No,
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct( AbsolutelyPositionedBox::construct(context, &info, display_inside, contents),
context,
root_element,
style,
display_inside,
contents,
),
)), )),
) )
} else if box_style.float.is_floating() { } else if box_style.float.is_floating() {
@ -286,20 +276,18 @@ fn construct_for_root_element<'dom>(
ContainsFloats::Yes, ContainsFloats::Yes,
BlockLevelBox::OutOfFlowFloatBox(FloatBox::construct( BlockLevelBox::OutOfFlowFloatBox(FloatBox::construct(
context, context,
root_element, &info,
style,
display_inside, display_inside,
contents, contents,
)), )),
) )
} else { } else {
let propagated_text_decoration_line = style.clone_text_decoration_line(); let propagated_text_decoration_line = info.style.clone_text_decoration_line();
( (
ContainsFloats::No, ContainsFloats::No,
BlockLevelBox::Independent(IndependentFormattingContext::construct( BlockLevelBox::Independent(IndependentFormattingContext::construct(
context, context,
root_element, &info,
style,
display_inside, display_inside,
contents, contents,
ContentSizesRequest::None, ContentSizesRequest::None,
@ -461,7 +449,7 @@ impl FragmentTree {
pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<OpaqueNode>) { pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<OpaqueNode>) {
self.find(|fragment, _| { self.find(|fragment, _| {
if let Some(tag) = fragment.tag().as_ref() { if let Some(tag) = fragment.tag().as_ref() {
set.remove(tag); set.remove(&tag.node());
} }
None::<()> None::<()>
}); });
@ -469,8 +457,9 @@ impl FragmentTree {
pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> { pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> {
let mut bounding_box = PhysicalRect::zero(); let mut bounding_box = PhysicalRect::zero();
let tag_to_find = Tag::Node(requested_node);
self.find(|fragment, containing_block| { self.find(|fragment, containing_block| {
if fragment.tag() != Some(requested_node) { if fragment.tag() != Some(tag_to_find) {
return None::<()>; return None::<()>;
} }
@ -507,7 +496,7 @@ impl FragmentTree {
pub fn get_border_dimensions_for_node(&self, requested_node: OpaqueNode) -> Rect<i32> { pub fn get_border_dimensions_for_node(&self, requested_node: OpaqueNode) -> Rect<i32> {
self.find(|fragment, containing_block| { self.find(|fragment, containing_block| {
let (style, padding_rect) = match fragment { let (style, padding_rect) = match fragment {
Fragment::Box(fragment) if fragment.tag == requested_node => { Fragment::Box(fragment) if fragment.tag.node() == requested_node => {
(&fragment.style, fragment.padding_rect()) (&fragment.style, fragment.padding_rect())
}, },
Fragment::AbsoluteOrFixedPositioned(_) | Fragment::AbsoluteOrFixedPositioned(_) |

View file

@ -3,10 +3,10 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
use crate::flexbox::FlexContainer; use crate::flexbox::FlexContainer;
use crate::flow::BlockFormattingContext; use crate::flow::BlockFormattingContext;
use crate::fragments::Fragment; use crate::fragments::{Fragment, Tag};
use crate::positioned::PositioningContext; use crate::positioned::PositioningContext;
use crate::replaced::ReplacedContent; use crate::replaced::ReplacedContent;
use crate::sizing::{BoxContentSizes, ContentSizesRequest}; use crate::sizing::{BoxContentSizes, ContentSizesRequest};
@ -14,7 +14,6 @@ use crate::style_ext::DisplayInside;
use crate::ContainingBlock; use crate::ContainingBlock;
use servo_arc::Arc; use servo_arc::Arc;
use std::convert::TryInto; use std::convert::TryInto;
use style::dom::OpaqueNode;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::Length; use style::values::computed::Length;
use style::values::specified::text::TextDecorationLine; use style::values::specified::text::TextDecorationLine;
@ -22,7 +21,7 @@ use style::values::specified::text::TextDecorationLine;
/// https://drafts.csswg.org/css-display/#independent-formatting-context /// https://drafts.csswg.org/css-display/#independent-formatting-context
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct IndependentFormattingContext { pub(crate) struct IndependentFormattingContext {
pub tag: OpaqueNode, pub tag: Tag,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub style: Arc<ComputedValues>, pub style: Arc<ComputedValues>,
@ -61,8 +60,7 @@ enum NonReplacedIFCKind<'a> {
impl IndependentFormattingContext { impl IndependentFormattingContext {
pub fn construct<'dom>( pub fn construct<'dom>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
@ -73,15 +71,14 @@ impl IndependentFormattingContext {
DisplayInside::Flow | DisplayInside::FlowRoot => { DisplayInside::Flow | DisplayInside::FlowRoot => {
let (bfc, content_sizes) = BlockFormattingContext::construct( let (bfc, content_sizes) = BlockFormattingContext::construct(
context, context,
node, info,
&style,
non_replaced, non_replaced,
content_sizes, content_sizes,
propagated_text_decoration_line, propagated_text_decoration_line,
); );
Self { Self {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
style, style: Arc::clone(&info.style),
content_sizes, content_sizes,
contents: IndependentFormattingContextContents::Flow(bfc), contents: IndependentFormattingContextContents::Flow(bfc),
} }
@ -89,25 +86,25 @@ impl IndependentFormattingContext {
DisplayInside::Flex => { DisplayInside::Flex => {
let (fc, content_sizes) = FlexContainer::construct( let (fc, content_sizes) = FlexContainer::construct(
context, context,
node, info,
&style,
non_replaced, non_replaced,
content_sizes, content_sizes,
propagated_text_decoration_line, propagated_text_decoration_line,
); );
Self { Self {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
style, style: Arc::clone(&info.style),
content_sizes, content_sizes,
contents: IndependentFormattingContextContents::Flex(fc), contents: IndependentFormattingContextContents::Flex(fc),
} }
}, },
}, },
Err(replaced) => { Err(replaced) => {
let content_sizes = content_sizes.compute(|| replaced.inline_content_sizes(&style)); let content_sizes =
content_sizes.compute(|| replaced.inline_content_sizes(&info.style));
Self { Self {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
style, style: Arc::clone(&info.style),
content_sizes, content_sizes,
contents: IndependentFormattingContextContents::Replaced(replaced), contents: IndependentFormattingContextContents::Replaced(replaced),
} }
@ -117,8 +114,7 @@ impl IndependentFormattingContext {
pub fn construct_for_text_runs<'dom>( pub fn construct_for_text_runs<'dom>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
style: Arc<ComputedValues>,
runs: impl Iterator<Item = crate::flow::inline::TextRun>, runs: impl Iterator<Item = crate::flow::inline::TextRun>,
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
propagated_text_decoration_line: TextDecorationLine, propagated_text_decoration_line: TextDecorationLine,
@ -130,8 +126,8 @@ impl IndependentFormattingContext {
propagated_text_decoration_line, propagated_text_decoration_line,
); );
Self { Self {
tag: node.as_opaque(), tag: Tag::from_node_and_style_info(info),
style, style: Arc::clone(&info.style),
content_sizes, content_sizes,
contents: IndependentFormattingContextContents::Flow(bfc), contents: IndependentFormattingContextContents::Flow(bfc),
} }

View file

@ -3,6 +3,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::cell::ArcRefCell; use crate::cell::ArcRefCell;
use crate::dom_traversal::{NodeAndStyleInfo, NodeExt, WhichPseudoElement};
use crate::geom::flow_relative::{Rect, Sides}; use crate::geom::flow_relative::{Rect, Sides};
use crate::geom::{PhysicalPoint, PhysicalRect}; use crate::geom::{PhysicalPoint, PhysicalRect};
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
@ -10,6 +11,7 @@ use crate::layout_debug;
use gfx::font::FontMetrics as GfxFontMetrics; use gfx::font::FontMetrics as GfxFontMetrics;
use gfx::text::glyph::GlyphStore; use gfx::text::glyph::GlyphStore;
use gfx_traits::print_tree::PrintTree; use gfx_traits::print_tree::PrintTree;
use gfx_traits::{combine_id_with_fragment_type, FragmentType};
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
use serde::ser::{Serialize, Serializer}; use serde::ser::{Serialize, Serializer};
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
@ -24,6 +26,42 @@ use style::values::specified::text::TextDecorationLine;
use style::Zero; use style::Zero;
use webrender_api::{FontInstanceKey, ImageKey}; use webrender_api::{FontInstanceKey, ImageKey};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
pub(crate) enum Tag {
Node(OpaqueNode),
BeforePseudo(OpaqueNode),
AfterPseudo(OpaqueNode),
}
impl Tag {
pub(crate) fn node(&self) -> OpaqueNode {
match self {
Self::Node(node) | Self::AfterPseudo(node) | Self::BeforePseudo(node) => *node,
}
}
pub(crate) fn to_display_list_fragment_id(&self) -> u64 {
let (node, content_type) = match self {
Self::Node(node) => (node, FragmentType::FragmentBody),
Self::AfterPseudo(node) => (node, FragmentType::BeforePseudoContent),
Self::BeforePseudo(node) => (node, FragmentType::AfterPseudoContent),
};
combine_id_with_fragment_type(node.id() as usize, content_type) as u64
}
pub(crate) fn from_node_and_style_info<'dom, Node>(info: &NodeAndStyleInfo<Node>) -> Self
where
Node: NodeExt<'dom>,
{
let opaque_node = info.node.as_opaque();
match info.pseudo_element_type {
None => Self::Node(opaque_node),
Some(WhichPseudoElement::Before) => Self::BeforePseudo(opaque_node),
Some(WhichPseudoElement::After) => Self::AfterPseudo(opaque_node),
}
}
}
#[derive(Serialize)] #[derive(Serialize)]
pub(crate) enum Fragment { pub(crate) enum Fragment {
Box(BoxFragment), Box(BoxFragment),
@ -41,7 +79,7 @@ pub(crate) struct AbsoluteOrFixedPositionedFragment {
#[derive(Serialize)] #[derive(Serialize)]
pub(crate) struct BoxFragment { pub(crate) struct BoxFragment {
pub tag: OpaqueNode, pub tag: Tag,
pub debug_id: DebugId, pub debug_id: DebugId,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub style: ServoArc<ComputedValues>, pub style: ServoArc<ComputedValues>,
@ -113,7 +151,7 @@ impl From<&GfxFontMetrics> for FontMetrics {
#[derive(Serialize)] #[derive(Serialize)]
pub(crate) struct TextFragment { pub(crate) struct TextFragment {
pub debug_id: DebugId, pub debug_id: DebugId,
pub tag: OpaqueNode, pub tag: Tag,
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub parent_style: ServoArc<ComputedValues>, pub parent_style: ServoArc<ComputedValues>,
pub rect: Rect<Length>, pub rect: Rect<Length>,
@ -148,7 +186,7 @@ impl Fragment {
position.inline += *offset; position.inline += *offset;
} }
pub fn tag(&self) -> Option<OpaqueNode> { pub fn tag(&self) -> Option<Tag> {
match self { match self {
Fragment::Box(fragment) => Some(fragment.tag), Fragment::Box(fragment) => Some(fragment.tag),
Fragment::Text(fragment) => Some(fragment.tag), Fragment::Text(fragment) => Some(fragment.tag),
@ -278,7 +316,7 @@ impl AnonymousFragment {
impl BoxFragment { impl BoxFragment {
pub fn new( pub fn new(
tag: OpaqueNode, tag: Tag,
style: ServoArc<ComputedValues>, style: ServoArc<ComputedValues>,
children: Vec<Fragment>, children: Vec<Fragment>,
content_rect: Rect<Length>, content_rect: Rect<Length>,

View file

@ -4,7 +4,7 @@
use crate::cell::ArcRefCell; use crate::cell::ArcRefCell;
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{Contents, NodeExt}; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt};
use crate::formatting_contexts::IndependentFormattingContext; use crate::formatting_contexts::IndependentFormattingContext;
use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment};
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
@ -71,25 +71,23 @@ pub(crate) enum AbsoluteBoxOffsets {
impl AbsolutelyPositionedBox { impl AbsolutelyPositionedBox {
pub fn construct<'dom>( pub fn construct<'dom>(
context: &LayoutContext, context: &LayoutContext,
node: impl NodeExt<'dom>, node_info: &NodeAndStyleInfo<impl NodeExt<'dom>>,
style: Arc<ComputedValues>,
display_inside: DisplayInside, display_inside: DisplayInside,
contents: Contents, contents: Contents,
) -> Self { ) -> Self {
// "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width // "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
let content_sizes = ContentSizesRequest::inline_if( let content_sizes = ContentSizesRequest::inline_if(
// If inline-size is non-auto, that value is used without shrink-to-fit // If inline-size is non-auto, that value is used without shrink-to-fit
!style.inline_size_is_length() && !node_info.style.inline_size_is_length() &&
// If it is, then the only case where shrink-to-fit is *not* used is // If it is, then the only case where shrink-to-fit is *not* used is
// if both offsets are non-auto, leaving inline-size as the only variable // if both offsets are non-auto, leaving inline-size as the only variable
// in the constraint equation. // in the constraint equation.
!style.inline_box_offsets_are_both_non_auto(), !node_info.style.inline_box_offsets_are_both_non_auto(),
); );
Self { Self {
contents: IndependentFormattingContext::construct( contents: IndependentFormattingContext::construct(
context, context,
node, node_info,
style,
display_inside, display_inside,
contents, contents,
content_sizes, content_sizes,

View file

@ -5,7 +5,7 @@
//! Utilities for querying the layout, as needed by the layout thread. //! Utilities for querying the layout, as needed by the layout thread.
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::flow::FragmentTree; use crate::flow::FragmentTree;
use crate::fragments::Fragment; use crate::fragments::{Fragment, Tag};
use app_units::Au; use app_units::Au;
use euclid::default::{Point2D, Rect}; use euclid::default::{Point2D, Rect};
use euclid::Size2D; use euclid::Size2D;
@ -250,10 +250,13 @@ pub fn process_resolved_style_request<'dom>(
let computed_style = let computed_style =
|| style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id)); || style.computed_value_to_string(PropertyDeclarationId::Longhand(longhand_id));
// We do not yet support pseudo content. let opaque = node.opaque();
if pseudo.is_some() { let tag_to_find = match *pseudo {
return computed_style(); None => Tag::Node(opaque),
} Some(PseudoElement::Before) => Tag::BeforePseudo(opaque),
Some(PseudoElement::After) => Tag::AfterPseudo(opaque),
Some(_) => unreachable!("Should have returned before this point."),
};
// https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle // https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle
// Here we are trying to conform to the specification that says that getComputedStyle // Here we are trying to conform to the specification that says that getComputedStyle
@ -287,9 +290,7 @@ pub fn process_resolved_style_request<'dom>(
fragment_tree fragment_tree
.find(|fragment, containing_block| { .find(|fragment, containing_block| {
let box_fragment = match fragment { let box_fragment = match fragment {
Fragment::Box(ref box_fragment) if box_fragment.tag == node.opaque() => { Fragment::Box(ref box_fragment) if box_fragment.tag == tag_to_find => box_fragment,
box_fragment
},
_ => return None, _ => return None,
}; };

View file

@ -1,10 +1,4 @@
[getComputedStyle-pseudo.html] [getComputedStyle-pseudo.html]
[Resolution of width is correct for ::before and ::after pseudo-elements of display: contents elements]
expected: FAIL
[Resolution of width is correct for ::before and ::after pseudo-elements]
expected: FAIL
[Item-based blockification of nonexistent pseudo-elements] [Item-based blockification of nonexistent pseudo-elements]
expected: FAIL expected: FAIL