mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Auto merge of #29887 - Loirooriol:float-inline-size-complete, r=mrobinson
Handle floats in BlockContainer::inline_content_sizes Typically, block-level contents are stacked vertically, so this was just taking the maximum size among all contents. However, floats can be stacked horizontally, so we need to sum their sizes. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #29874 <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
commit
836ae5fa48
4 changed files with 112 additions and 28 deletions
|
@ -690,12 +690,7 @@ impl FloatBox {
|
|||
.floats
|
||||
.lower_ceiling(sequential_layout_state.current_block_position_including_margins());
|
||||
|
||||
let style = match self.contents {
|
||||
IndependentFormattingContext::Replaced(ref replaced) => replaced.style.clone(),
|
||||
IndependentFormattingContext::NonReplaced(ref non_replaced) => {
|
||||
non_replaced.style.clone()
|
||||
},
|
||||
};
|
||||
let style = self.contents.style().clone();
|
||||
let float_context = &mut sequential_layout_state.floats;
|
||||
let box_fragment = positioning_context.layout_maybe_position_relative_fragment(
|
||||
layout_context,
|
||||
|
|
|
@ -25,6 +25,8 @@ use crate::ContainingBlock;
|
|||
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||
use rayon_croissant::ParallelIteratorExt;
|
||||
use servo_arc::Arc;
|
||||
use style::computed_values::clear::T as Clear;
|
||||
use style::computed_values::float::T as Float;
|
||||
use style::logical_geometry::WritingMode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::values::computed::{Length, LengthOrAuto};
|
||||
|
@ -107,6 +109,99 @@ impl BlockFormattingContext {
|
|||
}
|
||||
}
|
||||
|
||||
/// Finds the min/max-content inline size of the block-level children of a block container.
|
||||
/// The in-flow boxes will stack vertically, so we only need to consider the maximum size.
|
||||
/// But floats can flow horizontally depending on 'clear', so we may need to sum their sizes.
|
||||
/// CSS 2 does not define the exact algorithm, this logic is based on the behavior observed
|
||||
/// on Gecko and Blink.
|
||||
fn calculate_inline_content_size_for_block_level_boxes(
|
||||
boxes: &[ArcRefCell<BlockLevelBox>],
|
||||
layout_context: &LayoutContext,
|
||||
writing_mode: WritingMode,
|
||||
) -> ContentSizes {
|
||||
let get_box_info = |box_: &ArcRefCell<BlockLevelBox>| {
|
||||
let size = box_
|
||||
.borrow_mut()
|
||||
.inline_content_sizes(layout_context, writing_mode);
|
||||
if let BlockLevelBox::OutOfFlowFloatBox(ref float_box) = *box_.borrow_mut() {
|
||||
let style_box = &float_box.contents.style().get_box();
|
||||
(size, style_box.float, style_box.clear)
|
||||
} else {
|
||||
// The element may in fact have clearance, but the logic below ignores it,
|
||||
// so don't bother retrieving it from the style.
|
||||
(size, Float::None, Clear::None)
|
||||
}
|
||||
};
|
||||
|
||||
/// When iterating the block-level boxes to compute the inline content sizes,
|
||||
/// this struct contains the data accumulated up to the current box.
|
||||
struct AccumulatedData {
|
||||
/// The maximum size seen so far, not including trailing uncleared floats.
|
||||
max_size: ContentSizes,
|
||||
/// The size of the trailing uncleared floats with 'float: left'.
|
||||
left_floats: ContentSizes,
|
||||
/// The size of the trailing uncleared floats with 'float: right'.
|
||||
right_floats: ContentSizes,
|
||||
}
|
||||
|
||||
impl AccumulatedData {
|
||||
fn max_size_including_uncleared_floats(&self) -> ContentSizes {
|
||||
self.max_size.max(self.left_floats.add(&self.right_floats))
|
||||
}
|
||||
fn clear_floats(&mut self, clear: Clear) {
|
||||
match clear {
|
||||
Clear::Left => {
|
||||
self.max_size = self.max_size_including_uncleared_floats();
|
||||
self.left_floats = ContentSizes::zero();
|
||||
},
|
||||
Clear::Right => {
|
||||
self.max_size = self.max_size_including_uncleared_floats();
|
||||
self.right_floats = ContentSizes::zero();
|
||||
},
|
||||
Clear::Both => {
|
||||
self.max_size = self.max_size_including_uncleared_floats();
|
||||
self.left_floats = ContentSizes::zero();
|
||||
self.right_floats = ContentSizes::zero();
|
||||
},
|
||||
Clear::None => {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let accumulate = |mut data: AccumulatedData, (size, float, clear)| {
|
||||
if float == Float::None {
|
||||
// TODO: The first BFC root after a sequence of floats should appear next to them
|
||||
// (if it doesn't have clearance).
|
||||
data.clear_floats(Clear::Both);
|
||||
data.max_size = data.max_size.max(size);
|
||||
} else {
|
||||
data.clear_floats(clear);
|
||||
match float {
|
||||
Float::Left => data.left_floats = data.left_floats.add(&size),
|
||||
Float::Right => data.right_floats = data.right_floats.add(&size),
|
||||
Float::None => unreachable!(),
|
||||
}
|
||||
}
|
||||
data
|
||||
};
|
||||
let zero = AccumulatedData {
|
||||
max_size: ContentSizes::zero(),
|
||||
left_floats: ContentSizes::zero(),
|
||||
right_floats: ContentSizes::zero(),
|
||||
};
|
||||
let data = if layout_context.use_rayon {
|
||||
boxes
|
||||
.par_iter()
|
||||
.map(get_box_info)
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.fold(zero, accumulate)
|
||||
} else {
|
||||
boxes.iter().map(get_box_info).fold(zero, accumulate)
|
||||
};
|
||||
data.max_size_including_uncleared_floats()
|
||||
}
|
||||
|
||||
impl BlockContainer {
|
||||
fn layout(
|
||||
&self,
|
||||
|
@ -143,21 +238,11 @@ impl BlockContainer {
|
|||
writing_mode: WritingMode,
|
||||
) -> ContentSizes {
|
||||
match &self {
|
||||
Self::BlockLevelBoxes(boxes) if layout_context.use_rayon => boxes
|
||||
.par_iter()
|
||||
.map(|box_| {
|
||||
box_.borrow_mut()
|
||||
.inline_content_sizes(layout_context, writing_mode)
|
||||
})
|
||||
.reduce(ContentSizes::zero, ContentSizes::max),
|
||||
Self::BlockLevelBoxes(boxes) => boxes
|
||||
.iter()
|
||||
.map(|box_| {
|
||||
box_.borrow_mut()
|
||||
.inline_content_sizes(layout_context, writing_mode)
|
||||
})
|
||||
.reduce(ContentSizes::max)
|
||||
.unwrap_or_else(ContentSizes::zero),
|
||||
Self::BlockLevelBoxes(boxes) => calculate_inline_content_size_for_block_level_boxes(
|
||||
boxes,
|
||||
layout_context,
|
||||
writing_mode,
|
||||
),
|
||||
Self::InlineFormattingContext(context) => {
|
||||
context.inline_content_sizes(layout_context, writing_mode)
|
||||
},
|
||||
|
|
|
@ -33,13 +33,20 @@ impl ContentSizes {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn max(self, other: Self) -> Self {
|
||||
pub fn max(&self, other: Self) -> Self {
|
||||
Self {
|
||||
min_content: self.min_content.max(other.min_content),
|
||||
max_content: self.max_content.max(other.max_content),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&self, other: &Self) -> Self {
|
||||
Self {
|
||||
min_content: self.min_content.max(other.min_content),
|
||||
max_content: self.max_content + other.max_content,
|
||||
}
|
||||
}
|
||||
|
||||
/// Relevant to outer intrinsic inline sizes, for percentages from padding and margin.
|
||||
pub fn adjust_for_pbm_percentages(&mut self, percentages: Percentage) {
|
||||
// " Note that this may yield an infinite result, but undefined results
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
[flex-basis-intrinsics-001.html]
|
||||
[.flex-item 1]
|
||||
expected: FAIL
|
||||
|
||||
[.flex-item 2]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -20,11 +23,5 @@
|
|||
[.flex-item 6]
|
||||
expected: FAIL
|
||||
|
||||
[.flex-item 7]
|
||||
expected: FAIL
|
||||
|
||||
[.flex-item 9]
|
||||
expected: FAIL
|
||||
|
||||
[.flex-item 11]
|
||||
expected: FAIL
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue