Flex items in the box tree

This commit is contained in:
Simon Sapin 2020-06-02 14:26:45 +02:00
parent 64124f7a5e
commit ec548e849c
3 changed files with 121 additions and 25 deletions

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::flexbox::FlexLevelBox;
use crate::flow::inline::InlineLevelBox; use crate::flow::inline::InlineLevelBox;
use crate::flow::BlockLevelBox; use crate::flow::BlockLevelBox;
@ -17,4 +18,5 @@ pub(super) enum LayoutBox {
DisplayContents, DisplayContents,
BlockLevel(ArcRefCell<BlockLevelBox>), BlockLevel(ArcRefCell<BlockLevelBox>),
InlineLevel(ArcRefCell<InlineLevelBox>), InlineLevel(ArcRefCell<InlineLevelBox>),
FlexLevel(ArcRefCell<FlexLevelBox>),
} }

View file

@ -2,21 +2,33 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use crate::cell::ArcRefCell;
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::dom_traversal::{NodeExt, NonReplacedContents}; use crate::dom_traversal::{BoxSlot, Contents, NodeExt, NonReplacedContents, TraversalHandler};
use crate::formatting_contexts::IndependentLayout; use crate::element_data::LayoutBox;
use crate::positioned::PositioningContext; use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
use crate::sizing::{BoxContentSizes, ContentSizesRequest}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext};
use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest};
use crate::style_ext::DisplayGeneratingBox;
use crate::ContainingBlock; use crate::ContainingBlock;
use servo_arc::Arc; use servo_arc::Arc;
use std::borrow::Cow;
use style::properties::ComputedValues; use style::properties::ComputedValues;
use style::values::computed::Length;
use style::values::specified::text::TextDecorationLine; use style::values::specified::text::TextDecorationLine;
use style::Zero;
// FIXME: `min-width: auto` is not zero: https://drafts.csswg.org/css-flexbox/#min-size-auto // FIXME: `min-width: auto` is not zero: https://drafts.csswg.org/css-flexbox/#min-size-auto
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub(crate) struct FlexContainer { pub(crate) struct FlexContainer {
unimplemented_fallback: crate::flow::BlockFormattingContext, children: Vec<ArcRefCell<FlexLevelBox>>,
}
#[derive(Debug, Serialize)]
pub(crate) enum FlexLevelBox {
FlexItem(IndependentFormattingContext),
OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>),
} }
impl FlexContainer { impl FlexContainer {
@ -28,23 +40,86 @@ impl FlexContainer {
content_sizes: ContentSizesRequest, content_sizes: ContentSizesRequest,
propagated_text_decoration_line: TextDecorationLine, propagated_text_decoration_line: TextDecorationLine,
) -> (Self, BoxContentSizes) { ) -> (Self, BoxContentSizes) {
let (unimplemented_fallback, content_sizes) = let text_decoration_line =
crate::flow::BlockFormattingContext::construct( propagated_text_decoration_line | style.clone_text_decoration_line();
context, let mut builder = FlexContainerBuilder {
node, context,
style, text_decoration_line,
contents, flex_container: Self {
content_sizes, children: Vec::new(),
propagated_text_decoration_line,
);
(
Self {
unimplemented_fallback,
}, },
content_sizes, };
) contents.traverse(context, node, style, &mut builder);
let content_sizes = content_sizes.compute(|| {
// FIXME
ContentSizes::zero()
});
(builder.flex_container, content_sizes)
}
}
struct FlexContainerBuilder<'context> {
context: &'context LayoutContext<'context>,
text_decoration_line: TextDecorationLine,
flex_container: FlexContainer,
}
impl<'context, 'dom, Node: 'dom> TraversalHandler<'dom, Node> for FlexContainerBuilder<'context>
where
Node: NodeExt<'dom>,
{
fn handle_text(
&mut self,
node: Node,
text: Cow<'dom, str>,
parent_style: &Arc<ComputedValues>,
) {
// FIXME
let _ = node;
let _ = text;
let _ = parent_style;
} }
/// Or pseudo-element
fn handle_element(
&mut self,
node: Node,
style: &Arc<ComputedValues>,
display: DisplayGeneratingBox,
contents: Contents,
box_slot: BoxSlot<'dom>,
) {
let display_inside = match display {
DisplayGeneratingBox::OutsideInside { inside, .. } => inside,
};
let box_ = if style.get_box().position.is_absolutely_positioned() {
// https://drafts.csswg.org/css-flexbox/#abspos-items
ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new(
AbsolutelyPositionedBox::construct(
self.context,
node,
style.clone(),
display_inside,
contents,
),
)))
} else {
ArcRefCell::new(FlexLevelBox::FlexItem(IndependentFormattingContext::construct(
self.context,
node,
style.clone(),
display_inside,
contents,
ContentSizesRequest::None, // FIXME: request sizes when we start using them
self.text_decoration_line,
)))
};
self.flex_container.children.push(box_.clone());
box_slot.set(LayoutBox::FlexLevel(box_))
}
}
impl FlexContainer {
pub(crate) fn layout( pub(crate) fn layout(
&self, &self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
@ -52,11 +127,14 @@ impl FlexContainer {
containing_block: &ContainingBlock, containing_block: &ContainingBlock,
tree_rank: usize, tree_rank: usize,
) -> IndependentLayout { ) -> IndependentLayout {
self.unimplemented_fallback.layout( // FIXME
layout_context, let _ = layout_context;
positioning_context, let _ = positioning_context;
containing_block, let _ = containing_block;
tree_rank, let _ = tree_rank;
) IndependentLayout {
fragments: Vec::new(),
content_block_size: Length::zero(),
}
} }
} }

View file

@ -10,6 +10,7 @@ use crate::display_list::stacking_context::{
}; };
use crate::dom_traversal::{iter_child_nodes, Contents, NodeExt}; use crate::dom_traversal::{iter_child_nodes, Contents, NodeExt};
use crate::element_data::LayoutBox; use crate::element_data::LayoutBox;
use crate::flexbox::FlexLevelBox;
use crate::flow::construct::ContainsFloats; use crate::flow::construct::ContainsFloats;
use crate::flow::float::FloatBox; use crate::flow::float::FloatBox;
use crate::flow::inline::InlineLevelBox; use crate::flow::inline::InlineLevelBox;
@ -119,6 +120,7 @@ impl BoxTree {
enum UpdatePoint { enum UpdatePoint {
AbsolutelyPositionedBlockLevelBox(ArcRefCell<BlockLevelBox>), AbsolutelyPositionedBlockLevelBox(ArcRefCell<BlockLevelBox>),
AbsolutelyPositionedInlineLevelBox(ArcRefCell<InlineLevelBox>), AbsolutelyPositionedInlineLevelBox(ArcRefCell<InlineLevelBox>),
AbsolutelyPositionedFlexLevelBox(ArcRefCell<FlexLevelBox>),
} }
fn update_point<'dom, Node>( fn update_point<'dom, Node>(
@ -188,6 +190,14 @@ impl BoxTree {
}, },
_ => return None, _ => return None,
}, },
LayoutBox::FlexLevel(flex_level_box) => match &*flex_level_box.borrow() {
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(_)
if box_style.position.is_absolutely_positioned() =>
{
UpdatePoint::AbsolutelyPositionedFlexLevelBox(flex_level_box.clone())
},
_ => return None,
},
}; };
Some((primary_style.clone(), display_inside, update_point)) Some((primary_style.clone(), display_inside, update_point))
} }
@ -217,6 +227,12 @@ impl BoxTree {
out_of_flow_absolutely_positioned_box, out_of_flow_absolutely_positioned_box,
); );
}, },
UpdatePoint::AbsolutelyPositionedFlexLevelBox(flex_level_box) => {
*flex_level_box.borrow_mut() =
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(
out_of_flow_absolutely_positioned_box,
);
},
} }
return true; return true;
} }