mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
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:
parent
ea8cd36f0d
commit
c909c64378
1 changed files with 207 additions and 212 deletions
|
@ -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 function’s 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> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue