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,
};
use super::{FlexContainer, FlexLevelBox};
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout};
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
@ -77,6 +78,13 @@ struct FlexItem<'a> {
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
struct FlexLine<'a> {
items: &'a mut [FlexItem<'a>],
@ -158,14 +166,18 @@ impl FlexContainer {
// Absolutely-positioned children of the flex container may be interleaved
// 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.
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
.iter()
.map(|arcrefcell| {
let borrowed = arcrefcell.borrow_mut();
match &*borrowed {
FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(absolutely_positioned) => {
Ok(absolutely_positioned.clone())
FlexContent::AbsolutelyPositionedBox(absolutely_positioned.clone())
},
FlexLevelBox::FlexItem(_) => {
let item = AtomicRefMut::map(borrowed, |child| match child {
@ -173,69 +185,14 @@ impl FlexContainer {
_ => unreachable!(),
});
flex_items.push(item);
Err(())
FlexContent::FlexItemPlaceholder
},
}
})
.collect::<Vec<_>>();
let (mut flex_item_fragments, content_block_size) = layout(
layout_context,
positioning_context,
containing_block,
flex_items.iter_mut().map(|child| &mut **child),
);
let flex_item_boxes = 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.
// We have access to style for the flex container in `containing_block.style`,
// but resolving percentages there requires access
@ -389,7 +346,8 @@ fn layout<'context, 'boxes>(
container_main_size
},
};
let fragments_and_positioning_contexts = flex_lines
let mut flex_item_fragments = flex_lines
.into_iter()
.zip(line_cross_start_positions)
.flat_map(move |(mut line, line_cross_start_position)| {
@ -417,7 +375,44 @@ fn layout<'context, 'boxes>(
line.item_fragments
})
.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> {