mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
layout: Implement proper absolute child position for flexbox (#33346)
This implements the requirements outlined in the [flexbox specification] about how to position absolute children of flex containers. We must establish a static position rectangle (to use if all insets are auto) and also align the child into that rectangle. [flebox specification]: https://drafts.csswg.org/css-flexbox/#abspos-items Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
a3a86d5913
commit
d169a82d2e
20 changed files with 678 additions and 724 deletions
|
@ -11,6 +11,7 @@ use style::properties::ComputedValues;
|
|||
use style::values::computed::Length;
|
||||
use style::values::generics::box_::{GenericVerticalAlign, VerticalAlignKeyword};
|
||||
use style::values::generics::font::LineHeight;
|
||||
use style::values::specified::align::AlignFlags;
|
||||
use style::values::specified::box_::DisplayOutside;
|
||||
use style::values::specified::text::TextDecorationLine;
|
||||
use style::values::Either;
|
||||
|
@ -24,7 +25,7 @@ use crate::cell::ArcRefCell;
|
|||
use crate::fragment_tree::{
|
||||
BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment,
|
||||
};
|
||||
use crate::geom::{LogicalRect, LogicalVec2, ToLogical};
|
||||
use crate::geom::{LogicalRect, LogicalVec2};
|
||||
use crate::positioned::{
|
||||
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
||||
};
|
||||
|
@ -368,15 +369,13 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
};
|
||||
|
||||
let ifc_writing_mode = self.layout.containing_block.effective_writing_mode();
|
||||
if inner_state
|
||||
.flags
|
||||
.contains(LineLayoutInlineContainerFlags::HAD_ANY_FLOATS)
|
||||
{
|
||||
for fragment in inner_state.fragments.iter_mut() {
|
||||
if let Fragment::Float(box_fragment) = fragment {
|
||||
for fragment in inner_state.fragments.iter_mut() {
|
||||
match fragment {
|
||||
Fragment::Float(box_fragment) => {
|
||||
box_fragment.content_rect.origin -=
|
||||
pbm_sums.start_offset().to_physical_size(ifc_writing_mode);
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -404,7 +403,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
positioning_context
|
||||
.layout_collected_children(self.layout.layout_context, &mut fragment);
|
||||
positioning_context.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&fragment.content_rect.origin.to_logical(ifc_writing_mode),
|
||||
&fragment.content_rect.origin.to_vector(),
|
||||
PositioningContextLength::zero(),
|
||||
);
|
||||
self.current_positioning_context_mut()
|
||||
|
@ -413,7 +412,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
Either::Second(start_offset) => {
|
||||
self.current_positioning_context_mut()
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&fragment.content_rect.origin.to_logical(ifc_writing_mode),
|
||||
&fragment.content_rect.origin.to_vector(),
|
||||
start_offset,
|
||||
);
|
||||
},
|
||||
|
@ -526,11 +525,7 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
|
||||
if let Some(mut positioning_context) = atomic.positioning_context {
|
||||
positioning_context.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&atomic
|
||||
.fragment
|
||||
.content_rect
|
||||
.origin
|
||||
.to_logical(ifc_writing_mode),
|
||||
&atomic.fragment.content_rect.origin.to_vector(),
|
||||
PositioningContextLength::zero(),
|
||||
);
|
||||
self.current_positioning_context_mut()
|
||||
|
@ -574,10 +569,21 @@ impl<'layout_data, 'layout> LineItemLayout<'layout_data, 'layout> {
|
|||
}
|
||||
};
|
||||
|
||||
// Since alignment of absolutes in inlines is currently always `start`, the size of
|
||||
// of the static position rectangle does not matter.
|
||||
let static_position_rect = LogicalRect {
|
||||
start_corner: initial_start_corner,
|
||||
size: LogicalVec2::zero(),
|
||||
}
|
||||
.to_physical(self.layout.containing_block.effective_writing_mode());
|
||||
|
||||
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
|
||||
absolute.absolutely_positioned_box.clone(),
|
||||
initial_start_corner.into(),
|
||||
self.layout.containing_block,
|
||||
static_position_rect,
|
||||
LogicalVec2 {
|
||||
inline: AlignFlags::START,
|
||||
block: AlignFlags::START,
|
||||
},
|
||||
);
|
||||
let hoisted_fragment = hoisted_box.fragment.clone();
|
||||
self.current_positioning_context_mut().push(hoisted_box);
|
||||
|
|
|
@ -886,13 +886,13 @@ impl<'layout_dta> InlineFormattingContextLayout<'layout_dta> {
|
|||
},
|
||||
};
|
||||
|
||||
let line_rect = line_rect.to_physical(self.containing_block.effective_writing_mode());
|
||||
self.positioning_context
|
||||
.adjust_static_position_of_hoisted_fragments_with_offset(
|
||||
&line_rect.start_corner,
|
||||
&line_rect.origin.to_vector(),
|
||||
start_positioning_context_length,
|
||||
);
|
||||
|
||||
let line_rect = line_rect.to_physical(self.containing_block.effective_writing_mode());
|
||||
self.fragments
|
||||
.push(Fragment::Positioning(PositioningFragment::new_anonymous(
|
||||
line_rect, fragments,
|
||||
|
|
|
@ -15,6 +15,7 @@ use style::computed_values::float::T as Float;
|
|||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthOrAuto, Size};
|
||||
use style::values::specified::align::AlignFlags;
|
||||
use style::values::specified::{Display, TextAlignKeyword};
|
||||
use style::Zero;
|
||||
|
||||
|
@ -594,7 +595,6 @@ fn layout_block_level_children_in_parallel(
|
|||
placement_state.place_fragment_and_update_baseline(&mut fragment, None);
|
||||
child_positioning_context.adjust_static_position_of_hoisted_fragments(
|
||||
&fragment,
|
||||
containing_block.effective_writing_mode(),
|
||||
PositioningContextLength::zero(),
|
||||
);
|
||||
positioning_context.append(child_positioning_context);
|
||||
|
@ -632,7 +632,6 @@ fn layout_block_level_children_sequentially(
|
|||
.place_fragment_and_update_baseline(&mut fragment, Some(sequential_layout_state));
|
||||
positioning_context.adjust_static_position_of_hoisted_fragments(
|
||||
&fragment,
|
||||
containing_block.effective_writing_mode(),
|
||||
positioning_context_length_before_layout,
|
||||
);
|
||||
|
||||
|
@ -709,11 +708,14 @@ impl BlockLevelBox {
|
|||
BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => {
|
||||
let hoisted_box = AbsolutelyPositionedBox::to_hoisted(
|
||||
box_.clone(),
|
||||
// This is incorrect, however we do not know the
|
||||
// correct positioning until later, in place_block_level_fragment,
|
||||
// and this value will be adjusted there
|
||||
LogicalVec2::zero(),
|
||||
containing_block,
|
||||
// This is incorrect, however we do not know the correct positioning
|
||||
// until later, in PlacementState::place_fragment, and this value will be
|
||||
// adjusted there
|
||||
PhysicalRect::zero(),
|
||||
LogicalVec2 {
|
||||
inline: AlignFlags::START,
|
||||
block: AlignFlags::START,
|
||||
},
|
||||
);
|
||||
let hoisted_fragment = hoisted_box.fragment.clone();
|
||||
positioning_context.push(hoisted_box);
|
||||
|
@ -1817,11 +1819,17 @@ impl PlacementState {
|
|||
}
|
||||
},
|
||||
Fragment::AbsoluteOrFixedPositioned(fragment) => {
|
||||
let offset = LogicalVec2 {
|
||||
block: (self.current_margin.solve() + self.current_block_direction_position),
|
||||
inline: Au::zero(),
|
||||
};
|
||||
fragment.borrow_mut().adjust_offsets(offset);
|
||||
// The alignment of absolutes in block flow layout is always "start", so the size of
|
||||
// the static position rectangle does not matter.
|
||||
fragment.borrow_mut().static_position_rect = LogicalRect {
|
||||
start_corner: LogicalVec2 {
|
||||
block: (self.current_margin.solve() +
|
||||
self.current_block_direction_position),
|
||||
inline: Au::zero(),
|
||||
},
|
||||
size: LogicalVec2::zero(),
|
||||
}
|
||||
.to_physical(self.writing_mode);
|
||||
},
|
||||
Fragment::Float(box_fragment) => {
|
||||
let sequential_layout_state = sequential_layout_state
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue