Auto merge of #24243 - servo:box-construct, r=SimonSapin

Uncomment more stuff related to box construction

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/24243)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-09-23 17:00:25 -04:00 committed by GitHub
commit ee17eedf3a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 323 additions and 278 deletions

View file

@ -6,13 +6,15 @@ 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;
use style::selector_parser::PseudoElement;
#[derive(Clone, Copy)]
pub(super) enum WhichPseudoElement {
@ -43,7 +45,10 @@ pub(super) enum PseudoElementContentItem {
Replaced(ReplacedContent),
}
pub(super) trait TraversalHandler<Node> {
pub(super) trait TraversalHandler<'dom, Node>
where
Node: 'dom,
{
fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>);
/// Or pseudo-element
@ -52,14 +57,14 @@ pub(super) trait TraversalHandler<Node> {
style: &Arc<ComputedValues>,
display: DisplayGeneratingBox,
contents: Contents<Node>,
box_slot: BoxSlot,
box_slot: BoxSlot<'dom>,
);
}
fn traverse_children_of<'dom, Node>(
parent_element: Node,
context: &SharedStyleContext,
handler: &mut impl TraversalHandler<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
@ -81,7 +86,7 @@ fn traverse_children_of<'dom, Node>(
fn traverse_element<'dom, Node>(
element: Node,
context: &SharedStyleContext,
handler: &mut impl TraversalHandler<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
@ -94,7 +99,7 @@ fn traverse_element<'dom, Node>(
// <https://drafts.csswg.org/css-display-3/#valdef-display-contents>
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 +121,7 @@ fn traverse_pseudo_element<'dom, Node>(
which: WhichPseudoElement,
element: Node,
context: &SharedStyleContext,
handler: &mut impl TraversalHandler<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) where
Node: NodeExt<'dom>,
{
@ -126,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);
@ -140,33 +145,42 @@ fn traverse_pseudo_element<'dom, Node>(
fn traverse_pseudo_element_contents<'dom, Node>(
pseudo_element_style: &Arc<ComputedValues>,
context: &SharedStyleContext,
handler: &mut impl TraversalHandler<'dom, Node>,
items: Vec<PseudoElementContentItem>,
handler: &mut impl TraversalHandler<Node>,
) 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 dont 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::<Node::ConcreteElement>(
&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 dont keep pointers to boxes generated by contents of pseudo-elements
BoxSlot::dummy(),
)
},
}
}
@ -201,12 +215,12 @@ where
self,
inherited_style: &Arc<ComputedValues>,
context: &SharedStyleContext,
handler: &mut impl TraversalHandler<Node>,
handler: &mut impl TraversalHandler<'dom, Node>,
) {
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)
},
}
}
@ -239,22 +253,25 @@ where
}
pub(super) struct BoxSlot<'dom> {
slot: Option<AtomicRefMut<'dom, Option<LayoutBox>>>,
slot: Option<Arc<AtomicRefCell<Option<LayoutBox>>>>,
marker: marker<&'dom ()>,
}
impl<'dom> BoxSlot<'dom> {
pub fn new(mut slot: AtomicRefMut<'dom, Option<LayoutBox>>) -> Self {
*slot = None;
Self { slot: Some(slot) }
impl BoxSlot<'_> {
pub fn new(slot: Arc<AtomicRefCell<Option<LayoutBox>>>) -> 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,12 +279,12 @@ 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");
}
}
}
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<String>;
fn first_child(self) -> Option<Self>;
@ -276,15 +293,15 @@ pub(crate) trait NodeExt<'dom>: 'dom + Copy + Send + Sync {
fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>;
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>;
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);
}
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()
@ -320,27 +337,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| {
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);
match which {
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 +367,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.

View file

@ -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<LayoutBox>,
pub(super) self_box: Arc<AtomicRefCell<Option<LayoutBox>>>,
pub(super) pseudo_elements: Option<Box<PseudoElementBoxes>>,
}
#[derive(Default)]
pub(super) struct PseudoElementBoxes {
pub before: Option<LayoutBox>,
pub after: Option<LayoutBox>,
pub before: Arc<AtomicRefCell<Option<LayoutBox>>>,
pub after: Arc<AtomicRefCell<Option<LayoutBox>>>,
}
pub(super) enum LayoutBox {

View file

@ -9,13 +9,14 @@ 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;
use std::convert::TryInto;
use style::context::SharedStyleContext;
use style::properties::ComputedValues;
use style::selector_parser::PseudoElement;
impl BlockFormattingContext {
pub fn construct<'dom>(
@ -152,8 +153,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 +166,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,
@ -178,7 +177,7 @@ impl BlockContainer {
}
}
impl<'dom, Node> TraversalHandler<Node> for BlockContainerBuilder<'dom, '_, Node>
impl<'dom, Node> TraversalHandler<'dom, Node> for BlockContainerBuilder<'dom, '_, Node>
where
Node: NodeExt<'dom>,
{
@ -187,7 +186,7 @@ where
style: &Arc<ComputedValues>,
display: DisplayGeneratingBox,
contents: Contents<Node>,
box_slot: BoxSlot,
box_slot: BoxSlot<'dom>,
) {
match display {
DisplayGeneratingBox::OutsideInside { outside, inside } => match outside {
@ -195,21 +194,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 +361,79 @@ where
box_
}
// FIXME
// fn handle_block_level_element(
// &mut self,
// style: Arc<ComputedValues>,
// 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<ComputedValues>,
display_inside: DisplayInside,
contents: Contents<Node>,
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,
@ -514,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::<Node::ConcreteElement>(
&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<Arc<InlineLevelBox>> {

View file

@ -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<ComputedValues>,
// ) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
// let replaced = ReplacedContent::for_element(root_element, context);
fn construct_for_root_element<'dom>(
context: &SharedStyleContext<'_>,
root_element: impl NodeExt<'dom>,
) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) {
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<crate::geom::CssPx>) -> Vec<Fragment> {
// let initial_containing_block_size = Vec2 {
// inline: Length { px: viewport.width },
// block: Length {
// px: viewport.height,
// },
// };
impl BoxTreeRoot {
fn layout(&self, viewport: geom::Size<CSSPixel>) -> Vec<Fragment> {
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 documents 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 documents 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
}
}

View file

@ -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:single_keyword>
${helpers.predefined_type(
"float",

View file

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