Fix typing issues in flex layout (#30784)

* Use `Option` instead of `Result` when passing optional values into vector

Also renames vector and adds comment for clarity, just in case that's helpful

Signed-off-by: Joshua Holmes <joshua.phillip.holmes@gmail.com>

* Replace use of Option with new enum, , when seperating flex content

Signed-off-by: Joshua Holmes <joshua.phillip.holmes@gmail.com>

* Move global  function body into the  method

Signed-off-by: Joshua Holmes <joshua.phillip.holmes@gmail.com>

---------

Signed-off-by: Joshua Holmes <joshua.phillip.holmes@gmail.com>
This commit is contained in:
Joshua Holmes 2023-12-04 02:02:07 -08:00 committed by GitHub
parent ea8cd36f0d
commit c909c64378
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -23,6 +23,7 @@ use super::geom::{
FlexAxis, FlexRelativeRect, FlexRelativeSides, FlexRelativeVec2, MainStartCrossStart, FlexAxis, FlexRelativeRect, FlexRelativeSides, FlexRelativeVec2, MainStartCrossStart,
}; };
use super::{FlexContainer, FlexLevelBox}; use super::{FlexContainer, FlexLevelBox};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext; use crate::context::LayoutContext;
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout}; use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment}; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
@ -77,6 +78,13 @@ struct FlexItem<'a> {
align_self: AlignItems, align_self: AlignItems,
} }
/// Child of a FlexContainer. Can either be absolutely positioned, or not. If not,
/// a placeholder is used and flex content is stored outside of this enum.
enum FlexContent {
AbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>),
FlexItemPlaceholder,
}
/// A flex line with some intermediate results /// A flex line with some intermediate results
struct FlexLine<'a> { struct FlexLine<'a> {
items: &'a mut [FlexItem<'a>], items: &'a mut [FlexItem<'a>],
@ -158,14 +166,18 @@ impl FlexContainer {
// Absolutely-positioned children of the flex container may be interleaved // Absolutely-positioned children of the flex container may be interleaved
// with flex items. We need to preserve their relative order for correct painting order, // with flex items. We need to preserve their relative order for correct painting order,
// which is the order of `Fragment`s in this functions return value. // which is the order of `Fragment`s in this functions return value.
let original_order_with_absolutely_positioned = self //
// Example:
// absolutely_positioned_items_with_original_order = [Some(item), Some(item), None, Some(item), None]
// flex_items = [item, item]
let absolutely_positioned_items_with_original_order = self
.children .children
.iter() .iter()
.map(|arcrefcell| { .map(|arcrefcell| {
let borrowed = arcrefcell.borrow_mut(); let borrowed = arcrefcell.borrow_mut();
match &*borrowed { match &*borrowed {
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(absolutely_positioned) => { FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(absolutely_positioned) => {
Ok(absolutely_positioned.clone()) FlexContent::AbsolutelyPositionedBox(absolutely_positioned.clone())
}, },
FlexLevelBox::FlexItem(_) => { FlexLevelBox::FlexItem(_) => {
let item = AtomicRefMut::map(borrowed, |child| match child { let item = AtomicRefMut::map(borrowed, |child| match child {
@ -173,69 +185,14 @@ impl FlexContainer {
_ => unreachable!(), _ => unreachable!(),
}); });
flex_items.push(item); flex_items.push(item);
Err(()) FlexContent::FlexItemPlaceholder
}, },
} }
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let (mut flex_item_fragments, content_block_size) = layout( let flex_item_boxes = flex_items.iter_mut().map(|child| &mut **child);
layout_context,
positioning_context,
containing_block,
flex_items.iter_mut().map(|child| &mut **child),
);
let fragments = original_order_with_absolutely_positioned
.into_iter()
.map(|child_as_abspos| match child_as_abspos {
Err(()) => {
// The `()` here is a place-holder for a flex item.
// The `flex_item_fragments` iterator yields one fragment
// per flex item, in the original order.
let (fragment, mut child_positioning_context) =
flex_item_fragments.next().unwrap();
let fragment = Fragment::Box(fragment);
child_positioning_context.adjust_static_position_of_hoisted_fragments(
&fragment,
PositioningContextLength::zero(),
);
positioning_context.append(child_positioning_context);
fragment
},
Ok(absolutely_positioned) => {
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
absolutely_positioned,
LogicalVec2::zero(),
containing_block,
);
let hoisted_fragment = hoisted_box.fragment.clone();
positioning_context.push(hoisted_box);
Fragment::AbsoluteOrFixedPositioned(hoisted_fragment)
},
})
.collect::<Vec<_>>();
// There should be no more flex items
assert!(flex_item_fragments.next().is_none());
IndependentLayout {
fragments,
content_block_size,
}
}
}
/// Return one fragment for each flex item, in the provided order, and the used block-size.
fn layout<'context, 'boxes>(
layout_context: &LayoutContext,
positioning_context: &mut PositioningContext,
containing_block: &ContainingBlock,
flex_item_boxes: impl Iterator<Item = &'boxes mut IndependentFormattingContext>,
) -> (
impl Iterator<Item = (BoxFragment, PositioningContext)>,
Length,
) {
// FIXME: get actual min/max cross size for the flex container. // FIXME: get actual min/max cross size for the flex container.
// We have access to style for the flex container in `containing_block.style`, // We have access to style for the flex container in `containing_block.style`,
// but resolving percentages there requires access // but resolving percentages there requires access
@ -389,7 +346,8 @@ fn layout<'context, 'boxes>(
container_main_size container_main_size
}, },
}; };
let fragments_and_positioning_contexts = flex_lines
let mut flex_item_fragments = flex_lines
.into_iter() .into_iter()
.zip(line_cross_start_positions) .zip(line_cross_start_positions)
.flat_map(move |(mut line, line_cross_start_position)| { .flat_map(move |(mut line, line_cross_start_position)| {
@ -417,7 +375,44 @@ fn layout<'context, 'boxes>(
line.item_fragments line.item_fragments
}) })
.into_iter(); .into_iter();
(fragments_and_positioning_contexts, content_block_size)
let fragments = absolutely_positioned_items_with_original_order
.into_iter()
.map(|child_as_abspos| match child_as_abspos {
FlexContent::AbsolutelyPositionedBox(absolutely_positioned) => {
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
absolutely_positioned,
LogicalVec2::zero(),
containing_block,
);
let hoisted_fragment = hoisted_box.fragment.clone();
positioning_context.push(hoisted_box);
Fragment::AbsoluteOrFixedPositioned(hoisted_fragment)
},
FlexContent::FlexItemPlaceholder => {
// The `flex_item_fragments` iterator yields one fragment
// per flex item, in the original order.
let (fragment, mut child_positioning_context) =
flex_item_fragments.next().unwrap();
let fragment = Fragment::Box(fragment);
child_positioning_context.adjust_static_position_of_hoisted_fragments(
&fragment,
PositioningContextLength::zero(),
);
positioning_context.append(child_positioning_context);
fragment
},
})
.collect::<Vec<_>>();
// There should be no more flex items
assert!(flex_item_fragments.next().is_none());
IndependentLayout {
fragments,
content_block_size,
}
}
} }
impl<'a> FlexItem<'a> { impl<'a> FlexItem<'a> {