use script::layout_dom::ServoLayoutNode;
use crate::context::LayoutContext;
use crate::dom::{LayoutBox, NodeExt};
use crate::flexbox::FlexLevelBox;
use crate::flow::BlockLevelBox;
use crate::flow::inline::InlineItem;
use crate::fragment_tree::Fragment;
pub(crate) struct LayoutRoot<'dom> {
node: ServoLayoutNode<'dom>,
}
impl<'dom> TryFrom<ServoLayoutNode<'dom>> for LayoutRoot<'dom> {
type Error = ();
fn try_from(node: ServoLayoutNode<'dom>) -> Result<Self, Self::Error> {
if !node.is_absolutely_positioned() {
return Err(());
}
let mut is_layout_root = false;
node.with_layout_box_base(|base| {
let fragments = base.fragments();
is_layout_root =
fragments.len() == 1 && matches!(fragments.first(), Some(Fragment::LayoutRoot(..)));
});
if !is_layout_root {
return Err(());
}
Ok(Self { node })
}
}
impl LayoutRoot<'_> {
pub(crate) fn try_layout(&self, layout_context: &LayoutContext) -> bool {
let Some(inner_layout_data) = self.node.inner_layout_data_mut() else {
return false;
};
let layout_box = inner_layout_data.self_box.clone();
let layout_box = layout_box.borrow();
let Some(layout_box) = &*layout_box else {
return false;
};
let positioned_box = match layout_box {
LayoutBox::BlockLevel(block_level) => {
let mut block_level = block_level.borrow_mut();
match &mut *block_level {
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
positioned_box.clone()
},
_ => return false,
}
},
LayoutBox::InlineLevel(InlineItem::OutOfFlowAbsolutelyPositionedBox(
positioned_box,
_,
)) => positioned_box.clone(),
LayoutBox::FlexLevel(flex_level_box) => {
let mut flex_level_box = flex_level_box.borrow_mut();
match &mut *flex_level_box {
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(positioned_box) => {
positioned_box.clone()
},
_ => return false,
}
},
_ => return false,
};
let positioned_box = positioned_box.borrow();
let formatting_context = &positioned_box.context;
let fragments = formatting_context.base.fragments();
let Some(Fragment::LayoutRoot(layout_root_fragment)) = fragments.first() else {
return false;
};
let layout_inputs = formatting_context.layout_root_layout_inputs.borrow();
let Some(layout_inputs) = &*layout_inputs else {
return false;
};
layout_inputs
.layout(
layout_context,
formatting_context,
&layout_root_fragment.fragment,
)
.is_ok()
}
}