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,
|
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 function’s return value.
|
// 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
|
.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> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue