From c08cfbb5f32c81e51588322bc8106eff6776b978 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 19 Sep 2019 09:40:17 +0200 Subject: [PATCH 1/4] Cheat the system and use an Arc in BoxSlot Ideally we want to be able to borrow from the DOM during box construction but that's not playing very well at the moment with the current bridge between script and layout. --- components/layout_2020/dom_traversal.rs | 74 +++++++++++++----------- components/layout_2020/element_data.rs | 7 ++- components/layout_2020/flow/construct.rs | 4 +- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index 0e9e18a739e..8310751b517 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -6,10 +6,11 @@ use crate::element_data::{LayoutBox, LayoutDataForElement}; use crate::replaced::ReplacedContent; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside}; use crate::wrapper::GetRawData; -use atomic_refcell::AtomicRefMut; +use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use servo_arc::Arc; use std::convert::TryInto; +use std::marker::PhantomData as marker; use style::context::SharedStyleContext; use style::dom::TNode; use style::properties::ComputedValues; @@ -43,7 +44,10 @@ pub(super) enum PseudoElementContentItem { Replaced(ReplacedContent), } -pub(super) trait TraversalHandler { +pub(super) trait TraversalHandler<'dom, Node> +where + Node: 'dom, +{ fn handle_text(&mut self, text: String, parent_style: &Arc); /// Or pseudo-element @@ -52,14 +56,14 @@ pub(super) trait TraversalHandler { style: &Arc, display: DisplayGeneratingBox, contents: Contents, - box_slot: BoxSlot, + box_slot: BoxSlot<'dom>, ); } fn traverse_children_of<'dom, Node>( parent_element: Node, context: &SharedStyleContext, - handler: &mut impl TraversalHandler, + handler: &mut impl TraversalHandler<'dom, Node>, ) where Node: NodeExt<'dom>, { @@ -81,7 +85,7 @@ fn traverse_children_of<'dom, Node>( fn traverse_element<'dom, Node>( element: Node, context: &SharedStyleContext, - handler: &mut impl TraversalHandler, + handler: &mut impl TraversalHandler<'dom, Node>, ) where Node: NodeExt<'dom>, { @@ -94,7 +98,7 @@ fn traverse_element<'dom, Node>( // element.unset_boxes_in_subtree() } else { - element.layout_data_mut().self_box = Some(LayoutBox::DisplayContents); + *element.layout_data_mut().self_box.borrow_mut() = Some(LayoutBox::DisplayContents); traverse_children_of(element, context, handler) } }, @@ -116,7 +120,7 @@ fn traverse_pseudo_element<'dom, Node>( which: WhichPseudoElement, element: Node, context: &SharedStyleContext, - handler: &mut impl TraversalHandler, + handler: &mut impl TraversalHandler<'dom, Node>, ) where Node: NodeExt<'dom>, { @@ -141,7 +145,7 @@ fn traverse_pseudo_element<'dom, Node>( fn traverse_pseudo_element_contents<'dom, Node>( pseudo_element_style: &Arc, items: Vec, - handler: &mut impl TraversalHandler, + handler: &mut impl TraversalHandler<'dom, Node>, ) where Node: 'dom, { @@ -201,7 +205,7 @@ where self, inherited_style: &Arc, context: &SharedStyleContext, - handler: &mut impl TraversalHandler, + handler: &mut impl TraversalHandler<'dom, Node>, ) { match self { NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler), @@ -239,22 +243,25 @@ where } pub(super) struct BoxSlot<'dom> { - slot: Option>>, + slot: Option>>>, + marker: marker<&'dom ()>, } -impl<'dom> BoxSlot<'dom> { - pub fn new(mut slot: AtomicRefMut<'dom, Option>) -> Self { - *slot = None; - Self { slot: Some(slot) } +impl BoxSlot<'_> { + pub fn new(slot: Arc>>) -> Self { + *slot.borrow_mut() = None; + let slot = Some(slot); + Self { slot, marker } } pub fn dummy() -> Self { - Self { slot: None } + let slot = None; + Self { slot, marker } } pub fn set(mut self, box_: LayoutBox) { if let Some(slot) = &mut self.slot { - **slot = Some(box_) + *slot.borrow_mut() = Some(box_); } } } @@ -262,7 +269,7 @@ impl<'dom> BoxSlot<'dom> { impl Drop for BoxSlot<'_> { fn drop(&mut self) { if let Some(slot) = &mut self.slot { - assert!(slot.is_some(), "failed to set a layout box") + assert!(slot.borrow().is_some(), "failed to set a layout box"); } } } @@ -276,8 +283,8 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync { fn style(self, context: &SharedStyleContext) -> Arc; fn layout_data_mut(&self) -> AtomicRefMut; - fn element_box_slot(&self) -> BoxSlot; - fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot; + fn element_box_slot(&self) -> BoxSlot<'dom>; + fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom>; fn unset_pseudo_element_box(self, which: WhichPseudoElement); fn unset_boxes_in_subtree(self); } @@ -320,27 +327,25 @@ where .unwrap() } - fn element_box_slot(&self) -> BoxSlot { - BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| { - &mut data.self_box - })) + fn element_box_slot(&self) -> BoxSlot<'dom> { + BoxSlot::new(self.layout_data_mut().self_box.clone()) } - fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot { - BoxSlot::new(AtomicRefMut::map(self.layout_data_mut(), |data| { - let pseudos = data.pseudo_elements.get_or_insert_with(Default::default); - match which { - WhichPseudoElement::Before => &mut pseudos.before, - WhichPseudoElement::After => &mut pseudos.after, - } - })) + fn pseudo_element_box_slot(&self, which: WhichPseudoElement) -> BoxSlot<'dom> { + let mut data = self.layout_data_mut(); + let pseudos = data.pseudo_elements.get_or_insert_with(Default::default); + let cell = match which { + WhichPseudoElement::Before => &mut pseudos.before, + WhichPseudoElement::After => &mut pseudos.after, + }; + BoxSlot::new(cell.clone()) } fn unset_pseudo_element_box(self, which: WhichPseudoElement) { if let Some(pseudos) = &mut self.layout_data_mut().pseudo_elements { match which { - WhichPseudoElement::Before => pseudos.before = None, - WhichPseudoElement::After => pseudos.after = None, + WhichPseudoElement::Before => *pseudos.before.borrow_mut() = None, + WhichPseudoElement::After => *pseudos.after.borrow_mut() = None, } } } @@ -352,7 +357,8 @@ where let traverse_children = { let mut layout_data = node.layout_data_mut(); layout_data.pseudo_elements = None; - layout_data.self_box.take().is_some() + 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. diff --git a/components/layout_2020/element_data.rs b/components/layout_2020/element_data.rs index 17c27e1bfcd..fdf611a76c7 100644 --- a/components/layout_2020/element_data.rs +++ b/components/layout_2020/element_data.rs @@ -4,18 +4,19 @@ use crate::flow::inline::InlineLevelBox; use crate::flow::BlockLevelBox; +use atomic_refcell::AtomicRefCell; use servo_arc::Arc; #[derive(Default)] pub(crate) struct LayoutDataForElement { - pub(super) self_box: Option, + pub(super) self_box: Arc>>, pub(super) pseudo_elements: Option>, } #[derive(Default)] pub(super) struct PseudoElementBoxes { - pub before: Option, - pub after: Option, + pub before: Arc>>, + pub after: Arc>>, } pub(super) enum LayoutBox { diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index de590c950d4..559d57752df 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -178,7 +178,7 @@ impl BlockContainer { } } -impl<'dom, Node> TraversalHandler for BlockContainerBuilder<'dom, '_, Node> +impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node> where Node: NodeExt<'dom>, { @@ -187,7 +187,7 @@ where style: &Arc, display: DisplayGeneratingBox, contents: Contents, - box_slot: BoxSlot, + box_slot: BoxSlot<'dom>, ) { match display { DisplayGeneratingBox::OutsideInside { outside, inside } => match outside { From 9cef3eee65cf93ff591d3638a8a402a44fba0970 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 19 Sep 2019 11:58:07 +0200 Subject: [PATCH 2/4] Uncomment more stuff related to box construction --- components/layout_2020/flow/construct.rs | 173 +++++++------- components/layout_2020/flow/root.rs | 221 +++++++++--------- .../style/properties/longhands/box.mako.rs | 27 ++- components/style/values/computed/box.rs | 7 + 4 files changed, 226 insertions(+), 202 deletions(-) diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 559d57752df..23cc84a5f8b 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -9,7 +9,7 @@ use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, Te use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::positioned::AbsolutelyPositionedBox; use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside}; -use crate::IndependentFormattingContext; +use crate::{take, IndependentFormattingContext}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; @@ -152,8 +152,7 @@ impl BlockContainer { ); return (container, builder.contains_floats); } - // FIXME - // builder.end_ongoing_inline_formatting_context(); + builder.end_ongoing_inline_formatting_context(); } let mut contains_floats = builder.contains_floats; @@ -166,8 +165,7 @@ impl BlockContainer { |contains_floats, (intermediate, box_slot): (IntermediateBlockLevelBox<_>, BoxSlot<'_>)| { let (block_level_box, box_contains_floats) = intermediate.finish(context); *contains_floats |= box_contains_floats; - // FIXME - // box_slot.set(LayoutBox::BlockLevel(block_level_box.clone())); + box_slot.set(LayoutBox::BlockLevel(block_level_box.clone())); block_level_box }, |left, right| *left |= right, @@ -195,21 +193,21 @@ where self.handle_inline_level_element(style, inside, contents), )), DisplayOutside::Block => { - // FIXME + let box_style = style.get_box(); // Floats and abspos cause blockification, so they only happen in this case. // https://drafts.csswg.org/css2/visuren.html#dis-pos-flo - // if style.box_.position.is_absolutely_positioned() { - // self.handle_absolutely_positioned_element( - // style.clone(), - // inside, - // contents, - // box_slot, - // ) - // } else if style.box_.float.is_floating() { - // self.handle_float_element(style.clone(), inside, contents, box_slot) - // } else { - // self.handle_block_level_element(style.clone(), inside, contents, box_slot) - // } + if box_style.position.is_absolutely_positioned() { + self.handle_absolutely_positioned_element( + style.clone(), + inside, + contents, + box_slot, + ) + } else if box_style.float.is_floating() { + self.handle_float_element(style.clone(), inside, contents, box_slot) + } else { + self.handle_block_level_element(style.clone(), inside, contents, box_slot) + } }, DisplayOutside::None => panic!(":("), }, @@ -362,80 +360,79 @@ where box_ } - // FIXME - // fn handle_block_level_element( - // &mut self, - // style: Arc, - // display_inside: DisplayInside, - // contents: Contents, - // box_slot: BoxSlot<'a>, - // ) { - // // We just found a block level element, all ongoing inline level boxes - // // need to be split around it. We iterate on the fragmented inline - // // level box stack to take their contents and set their first_fragment - // // field to false, for the fragmented inline level boxes that will - // // come after the block level element. - // let mut fragmented_inline_boxes = - // self.ongoing_inline_boxes_stack - // .iter_mut() - // .rev() - // .map(|ongoing| { - // let fragmented = InlineBox { - // style: ongoing.style.clone(), - // first_fragment: ongoing.first_fragment, - // // The fragmented boxes before the block level element - // // are obviously not the last fragment. - // last_fragment: false, - // children: take(&mut ongoing.children), - // }; - // ongoing.first_fragment = false; - // fragmented - // }); + fn handle_block_level_element( + &mut self, + style: Arc, + display_inside: DisplayInside, + contents: Contents, + box_slot: BoxSlot<'dom>, + ) { + // We just found a block level element, all ongoing inline level boxes + // need to be split around it. We iterate on the fragmented inline + // level box stack to take their contents and set their first_fragment + // field to false, for the fragmented inline level boxes that will + // come after the block level element. + let mut fragmented_inline_boxes = + self.ongoing_inline_boxes_stack + .iter_mut() + .rev() + .map(|ongoing| { + let fragmented = InlineBox { + style: ongoing.style.clone(), + first_fragment: ongoing.first_fragment, + // The fragmented boxes before the block level element + // are obviously not the last fragment. + last_fragment: false, + children: take(&mut ongoing.children), + }; + ongoing.first_fragment = false; + fragmented + }); - // if let Some(last) = fragmented_inline_boxes.next() { - // // There were indeed some ongoing inline level boxes before - // // the block, we accumulate them as a single inline level box - // // to be pushed to the ongoing inline formatting context. - // let mut fragmented_inline = InlineLevelBox::InlineBox(last); - // for mut fragmented_parent_inline_box in fragmented_inline_boxes { - // fragmented_parent_inline_box - // .children - // .push(Arc::new(fragmented_inline)); - // fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box); - // } + if let Some(last) = fragmented_inline_boxes.next() { + // There were indeed some ongoing inline level boxes before + // the block, we accumulate them as a single inline level box + // to be pushed to the ongoing inline formatting context. + let mut fragmented_inline = InlineLevelBox::InlineBox(last); + for mut fragmented_parent_inline_box in fragmented_inline_boxes { + fragmented_parent_inline_box + .children + .push(Arc::new(fragmented_inline)); + fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box); + } - // self.ongoing_inline_formatting_context - // .inline_level_boxes - // .push(Arc::new(fragmented_inline)); - // } + self.ongoing_inline_formatting_context + .inline_level_boxes + .push(Arc::new(fragmented_inline)); + } - // // We found a block level element, so the ongoing inline formatting - // // context needs to be ended. - // self.end_ongoing_inline_formatting_context(); + // We found a block level element, so the ongoing inline formatting + // context needs to be ended. + self.end_ongoing_inline_formatting_context(); - // let intermediate_box = match contents.try_into() { - // Ok(contents) => match display_inside { - // DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock { - // style, - // contents: IntermediateBlockContainer::Deferred { contents }, - // }, - // _ => IntermediateBlockLevelBox::Independent { - // style, - // display_inside, - // contents: contents.into(), - // }, - // }, - // Err(contents) => { - // let contents = Contents::Replaced(contents); - // IntermediateBlockLevelBox::Independent { - // style, - // display_inside, - // contents, - // } - // } - // }; - // self.block_level_boxes.push((intermediate_box, box_slot)) - // } + let intermediate_box = match contents.try_into() { + Ok(contents) => match display_inside { + DisplayInside::Flow => IntermediateBlockLevelBox::SameFormattingContextBlock { + style, + contents: IntermediateBlockContainer::Deferred { contents }, + }, + _ => IntermediateBlockLevelBox::Independent { + style, + display_inside, + contents: contents.into(), + }, + }, + Err(contents) => { + let contents = Contents::Replaced(contents); + IntermediateBlockLevelBox::Independent { + style, + display_inside, + contents, + } + }, + }; + self.block_level_boxes.push((intermediate_box, box_slot)) + } fn handle_absolutely_positioned_element( &mut self, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 08a23397506..b1a43ae28be 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -2,7 +2,25 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use super::*; +use crate::dom_traversal::{Contents, NodeExt}; +use crate::flow::construct::ContainsFloats; +use crate::flow::float::FloatBox; +use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; +use crate::fragments::Fragment; +use crate::geom; +use crate::geom::flow_relative::Vec2; +use crate::positioned::AbsolutelyPositionedBox; +use crate::replaced::ReplacedContent; +use crate::style_ext::{ + Direction, Display, DisplayGeneratingBox, DisplayInside, DisplayOutside, WritingMode, +}; +use crate::{ContainingBlock, DefiniteContainingBlock, IndependentFormattingContext}; +use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator}; +use servo_arc::Arc; +use style::context::SharedStyleContext; +use style::properties::ComputedValues; +use style::values::computed::{Length, LengthOrAuto}; +use style_traits::CSSPixel; // FIXME // impl crate::dom::Document { @@ -16,114 +34,107 @@ use super::*; struct BoxTreeRoot(BlockFormattingContext); -// FIXME -// impl BoxTreeRoot { -// pub fn construct(document: &dom::Document) -> Self { -// let author_styles = &document.parse_stylesheets(); -// let context = Context { -// document, -// author_styles, -// }; -// let root_element = document.root_element(); -// let style = style_for_element(context.author_styles, context.document, root_element, None); -// let (contains_floats, boxes) = construct_for_root_element(&context, root_element, style); -// Self(BlockFormattingContext { -// contains_floats: contains_floats == ContainsFloats::Yes, -// contents: BlockContainer::BlockLevelBoxes(boxes), -// }) -// } -// } +impl BoxTreeRoot { + pub fn construct<'dom>( + context: &SharedStyleContext<'_>, + root_element: impl NodeExt<'dom>, + ) -> Self { + let (contains_floats, boxes) = construct_for_root_element(&context, root_element); + Self(BlockFormattingContext { + contains_floats: contains_floats == ContainsFloats::Yes, + contents: BlockContainer::BlockLevelBoxes(boxes), + }) + } +} -// fn construct_for_root_element( -// context: &Context, -// root_element: dom::NodeId, -// style: Arc, -// ) -> (ContainsFloats, Vec>) { -// let replaced = ReplacedContent::for_element(root_element, context); +fn construct_for_root_element<'dom>( + context: &SharedStyleContext<'_>, + root_element: impl NodeExt<'dom>, +) -> (ContainsFloats, Vec>) { + let style = root_element.style(context); + let replaced = ReplacedContent::for_element(root_element, context); + let box_style = style.get_box(); -// let display_inside = match style.box_.display { -// Display::None => return (ContainsFloats::No, Vec::new()), -// Display::Contents if replaced.is_some() => { -// // 'display: contents' computes to 'none' for replaced elements -// return (ContainsFloats::No, Vec::new()); -// } -// // https://drafts.csswg.org/css-display-3/#transformations -// Display::Contents => DisplayInside::Flow, -// // The root element is blockified, ignore DisplayOutside -// Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside, -// }; + let display_inside = match Display::from(box_style.display) { + Display::None => return (ContainsFloats::No, Vec::new()), + Display::Contents if replaced.is_some() => { + // 'display: contents' computes to 'none' for replaced elements + return (ContainsFloats::No, Vec::new()); + }, + // https://drafts.csswg.org/css-display-3/#transformations + Display::Contents => DisplayInside::Flow, + // The root element is blockified, ignore DisplayOutside + Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { inside, .. }) => inside, + }; -// if let Some(replaced) = replaced { -// let _box = match replaced {}; -// #[allow(unreachable_code)] -// { -// return (ContainsFloats::No, vec![Arc::new(_box)]); -// } -// } + if let Some(replaced) = replaced { + let _box = match replaced {}; + #[allow(unreachable_code)] + { + return (ContainsFloats::No, vec![Arc::new(_box)]); + } + } -// let contents = IndependentFormattingContext::construct( -// context, -// &style, -// display_inside, -// Contents::OfElement(root_element), -// ); -// if style.box_.position.is_absolutely_positioned() { -// ( -// ContainsFloats::No, -// vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( -// AbsolutelyPositionedBox { style, contents }, -// ))], -// ) -// } else if style.box_.float.is_floating() { -// ( -// ContainsFloats::Yes, -// vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox { -// contents, -// style, -// }))], -// ) -// } else { -// ( -// ContainsFloats::No, -// vec![Arc::new(BlockLevelBox::Independent { style, contents })], -// ) -// } -// } + let contents = IndependentFormattingContext::construct( + context, + &style, + display_inside, + Contents::OfElement(root_element), + ); + if box_style.position.is_absolutely_positioned() { + ( + ContainsFloats::No, + vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( + AbsolutelyPositionedBox { style, contents }, + ))], + ) + } else if box_style.float.is_floating() { + ( + ContainsFloats::Yes, + vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox { + contents, + style, + }))], + ) + } else { + ( + ContainsFloats::No, + vec![Arc::new(BlockLevelBox::Independent { style, contents })], + ) + } +} -// impl BoxTreeRoot { -// fn layout(&self, viewport: crate::geom::Size) -> Vec { -// let initial_containing_block_size = Vec2 { -// inline: Length { px: viewport.width }, -// block: Length { -// px: viewport.height, -// }, -// }; +impl BoxTreeRoot { + fn layout(&self, viewport: geom::Size) -> Vec { + let initial_containing_block_size = Vec2 { + inline: Length::new(viewport.width), + block: Length::new(viewport.height), + }; -// let initial_containing_block = ContainingBlock { -// inline_size: initial_containing_block_size.inline, -// block_size: LengthOrAuto::Length(initial_containing_block_size.block), -// // FIXME: use the document’s mode: -// // https://drafts.csswg.org/css-writing-modes/#principal-flow -// mode: (WritingMode::HorizontalTb, Direction::Ltr), -// }; -// let dummy_tree_rank = 0; -// let mut absolutely_positioned_fragments = vec![]; -// let mut fragments = self.0.layout( -// &initial_containing_block, -// &mut absolutely_positioned_fragments, -// dummy_tree_rank, -// &mut PlacementState::root(), -// ); + let initial_containing_block = ContainingBlock { + inline_size: initial_containing_block_size.inline, + block_size: LengthOrAuto::LengthPercentage(initial_containing_block_size.block), + // FIXME: use the document’s mode: + // https://drafts.csswg.org/css-writing-modes/#principal-flow + mode: (WritingMode::HorizontalTb, Direction::Ltr), + }; + let dummy_tree_rank = 0; + let mut absolutely_positioned_fragments = vec![]; + let mut flow_children = self.0.layout( + &initial_containing_block, + dummy_tree_rank, + &mut absolutely_positioned_fragments, + ); -// let initial_containing_block = DefiniteContainingBlock { -// size: initial_containing_block_size, -// mode: initial_containing_block.mode, -// }; -// fragments.par_extend( -// absolutely_positioned_fragments -// .par_iter() -// .map(|a| a.layout(&initial_containing_block)), -// ); -// fragments -// } -// } + let initial_containing_block = DefiniteContainingBlock { + size: initial_containing_block_size, + mode: initial_containing_block.mode, + }; + flow_children.fragments.par_extend( + absolutely_positioned_fragments + .par_iter() + .map(|a| a.layout(&initial_containing_block)), + ); + flow_children.fragments + } +} diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 4dcc43aec23..2fd69229878 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -42,15 +42,24 @@ ${helpers.single_keyword( spec="Internal (not web-exposed)", )} -${helpers.single_keyword( - "position", - "static absolute relative fixed" + (" sticky" if engine in ["gecko", "servo-2013"] else ""), - engines="gecko servo-2013 servo-2020", - animation_value_type="discrete", - flags="CREATES_STACKING_CONTEXT ABSPOS_CB", - spec="https://drafts.csswg.org/css-position/#position-property", - servo_restyle_damage="rebuild_and_reflow", -)} +<%helpers:single_keyword + name="position" + values="static absolute relative fixed ${'sticky' if engine in ['gecko', 'servo-2013'] else ''}" + engines="gecko servo-2013 servo-2020" + animation_value_type="discrete" + flags="CREATES_STACKING_CONTEXT ABSPOS_CB" + spec="https://drafts.csswg.org/css-position/#position-property" + servo_restyle_damage="rebuild_and_reflow" +> +impl computed_value::T { + pub fn is_absolutely_positioned(self) -> bool { + match self { + Self::Absolute | Self::Fixed => true, + _ => false, + } + } +} + ${helpers.predefined_type( "float", diff --git a/components/style/values/computed/box.rs b/components/style/values/computed/box.rs index 4cd16b1cd9e..d5adeb206a6 100644 --- a/components/style/values/computed/box.rs +++ b/components/style/values/computed/box.rs @@ -61,6 +61,13 @@ pub enum Float { None, } +impl Float { + /// Returns true if `self` is not `None`. + pub fn is_floating(self) -> bool { + self != Self::None + } +} + impl ToComputedValue for SpecifiedFloat { type ComputedValue = Float; From 0c156c60c279a893fb08c72433ba98a26650607d Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Fri, 20 Sep 2019 17:00:12 +0200 Subject: [PATCH 3/4] Handle anonymous style in end_inline_formatting_context --- components/layout_2020/dom_traversal.rs | 4 +-- components/layout_2020/flow/construct.rs | 32 +++++++++++++----------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index 8310751b517..b3a58cb2ade 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -274,7 +274,7 @@ impl Drop for BoxSlot<'_> { } } -pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync { +pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode + Send + Sync { fn is_element(self) -> bool; fn as_text(self) -> Option; fn first_child(self) -> Option; @@ -291,7 +291,7 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync { impl<'dom, T> NodeExt<'dom> for T where - T: 'dom + LayoutNode + Send + Sync, + T: 'dom + Copy + LayoutNode + Send + Sync, { fn is_element(self) -> bool { self.to_threadsafe().as_element().is_some() diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 23cc84a5f8b..6b2027a8794 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -16,6 +16,7 @@ use servo_arc::Arc; use std::convert::TryInto; use style::context::SharedStyleContext; use style::properties::ComputedValues; +use style::selector_parser::PseudoElement; impl BlockFormattingContext { pub fn construct<'dom>( @@ -511,22 +512,25 @@ where return; } + let context = self.context; let block_container_style = self.block_container_style; - // FIXME - // let anonymous_style = self.anonymous_style.get_or_insert_with(|| { - // // If parent_style is None, the parent is the document node, - // // in which case anonymous inline boxes should inherit their - // // styles from initial values. - // ComputedValues::anonymous_inheriting_from(Some(block_container_style)) - // }); + let anonymous_style = self.anonymous_style.get_or_insert_with(|| { + context + .stylist + .style_for_anonymous::( + &context.guards, + &PseudoElement::ServoText, + &block_container_style, + ) + }); - // let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock { - // style: anonymous_style.clone(), - // contents: IntermediateBlockContainer::InlineFormattingContext(take( - // &mut self.ongoing_inline_formatting_context, - // )), - // }; - // self.block_level_boxes.push((box_, BoxSlot::dummy())) + let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock { + style: anonymous_style.clone(), + contents: IntermediateBlockContainer::InlineFormattingContext(take( + &mut self.ongoing_inline_formatting_context, + )), + }; + self.block_level_boxes.push((box_, BoxSlot::dummy())) } fn current_inline_level_boxes(&mut self) -> &mut Vec> { From 053a3d5a5a8fee080ebc83a71182c3ef8b85cc47 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 23 Sep 2019 10:54:36 +0200 Subject: [PATCH 4/4] Handle anonymous style in traverse_pseudo_element_contents --- components/layout_2020/dom_traversal.rs | 54 +++++++++++++++---------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index b3a58cb2ade..c1ac55c2bfb 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -14,6 +14,7 @@ use std::marker::PhantomData as marker; use style::context::SharedStyleContext; use style::dom::TNode; use style::properties::ComputedValues; +use style::selector_parser::PseudoElement; #[derive(Clone, Copy)] pub(super) enum WhichPseudoElement { @@ -130,7 +131,7 @@ fn traverse_pseudo_element<'dom, Node>( Display::Contents => { element.unset_pseudo_element_box(which); let items = generate_pseudo_element_content(&style, element, context); - traverse_pseudo_element_contents(&style, items, handler); + traverse_pseudo_element_contents(&style, context, handler, items); }, Display::GeneratingBox(display) => { let items = generate_pseudo_element_content(&style, element, context); @@ -144,33 +145,42 @@ fn traverse_pseudo_element<'dom, Node>( fn traverse_pseudo_element_contents<'dom, Node>( pseudo_element_style: &Arc, - items: Vec, + context: &SharedStyleContext, handler: &mut impl TraversalHandler<'dom, Node>, + items: Vec, ) where - Node: 'dom, + Node: NodeExt<'dom>, { - // let mut anonymous_style = None; + let mut anonymous_style = None; for item in items { match item { PseudoElementContentItem::Text(text) => handler.handle_text(text, pseudo_element_style), PseudoElementContentItem::Replaced(contents) => { - // FIXME - // let item_style = anonymous_style.get_or_insert_with(|| { - // ComputedValues::anonymous_inheriting_from(Some(pseudo_element_style)) - // }); - // let display_inline = DisplayGeneratingBox::OutsideInside { - // outside: DisplayOutside::Inline, - // inside: DisplayInside::Flow, - // }; - // // `display` is not inherited, so we get the initial value - // debug_assert!(item_style.box_.display == Display::GeneratingBox(display_inline)); - // handler.handle_element( - // item_style, - // display_inline, - // Contents::Replaced(contents), - // // We don’t keep pointers to boxes generated by contents of pseudo-elements - // BoxSlot::dummy(), - // ) + let item_style = anonymous_style.get_or_insert_with(|| { + context + .stylist + .style_for_anonymous::( + &context.guards, + &PseudoElement::ServoText, + &pseudo_element_style, + ) + }); + let display_inline = DisplayGeneratingBox::OutsideInside { + outside: DisplayOutside::Inline, + inside: DisplayInside::Flow, + }; + // `display` is not inherited, so we get the initial value + debug_assert!( + Display::from(item_style.get_box().display) == + Display::GeneratingBox(display_inline) + ); + handler.handle_element( + item_style, + display_inline, + Contents::Replaced(contents), + // We don’t keep pointers to boxes generated by contents of pseudo-elements + BoxSlot::dummy(), + ) }, } } @@ -210,7 +220,7 @@ where match self { NonReplacedContents::OfElement(node) => traverse_children_of(node, context, handler), NonReplacedContents::OfPseudoElement(items) => { - traverse_pseudo_element_contents(inherited_style, items, handler) + traverse_pseudo_element_contents(inherited_style, context, handler, items) }, } }