mirror of
https://github.com/servo/servo.git
synced 2025-07-16 03:43:38 +01:00
layout: Unify layout logic for replaced and non-replaced floats&atomics (#37897)
Laying out a float or atomic inline will now use the same logic regardless of whether it's replaced or not. This reduces the amount of code, and should have no observable effect. Testing: Unneeded (no behavior change) This part of #37942 Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
70c57c6136
commit
47c56d8d74
4 changed files with 94 additions and 146 deletions
|
@ -2076,11 +2076,8 @@ impl IndependentFormattingContext {
|
|||
.content_rect
|
||||
.translate(pbm_physical_offset.to_vector());
|
||||
|
||||
// Apply baselines if necessary.
|
||||
let mut fragment = match baselines {
|
||||
Some(baselines) => fragment.with_baselines(baselines),
|
||||
None => fragment,
|
||||
};
|
||||
// Apply baselines.
|
||||
fragment = fragment.with_baselines(baselines);
|
||||
|
||||
// Lay out absolutely positioned children if this new atomic establishes a containing block
|
||||
// for absolutes.
|
||||
|
|
|
@ -2226,7 +2226,7 @@ fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &Containi
|
|||
|
||||
pub(crate) struct IndependentFloatOrAtomicLayoutResult {
|
||||
pub fragment: BoxFragment,
|
||||
pub baselines: Option<Baselines>,
|
||||
pub baselines: Baselines,
|
||||
pub pbm_sums: LogicalSides<Au>,
|
||||
}
|
||||
|
||||
|
@ -2238,6 +2238,7 @@ impl IndependentFormattingContext {
|
|||
containing_block: &ContainingBlock,
|
||||
) -> IndependentFloatOrAtomicLayoutResult {
|
||||
let style = self.style();
|
||||
let writing_mode = style.writing_mode;
|
||||
let container_writing_mode = containing_block.style.writing_mode;
|
||||
let layout_style = self.layout_style();
|
||||
let content_box_sizes_and_pbm =
|
||||
|
@ -2245,115 +2246,97 @@ impl IndependentFormattingContext {
|
|||
let pbm = &content_box_sizes_and_pbm.pbm;
|
||||
let margin = pbm.margin.auto_is(Au::zero);
|
||||
let pbm_sums = pbm.padding + pbm.border + margin;
|
||||
let preferred_aspect_ratio = self.preferred_aspect_ratio(&pbm.padding_border_sums);
|
||||
let is_table = self.is_table();
|
||||
|
||||
let (fragments, content_rect, baselines, specific_layout_info) = match &self.contents {
|
||||
IndependentFormattingContextContents::Replaced(replaced) => {
|
||||
// Floats and atomic inlines can't collapse margins with their parent,
|
||||
// so don't ignore block margins when resolving a stretch block size.
|
||||
// https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
|
||||
let ignore_block_margins_for_stretch = LogicalSides1D::new(false, false);
|
||||
let available_inline_size =
|
||||
Au::zero().max(containing_block.size.inline - pbm_sums.inline_sum());
|
||||
let available_block_size = containing_block
|
||||
.size
|
||||
.block
|
||||
.to_definite()
|
||||
.map(|block_size| Au::zero().max(block_size - pbm_sums.block_sum()));
|
||||
|
||||
// https://drafts.csswg.org/css2/visudet.html#float-replaced-width
|
||||
// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height
|
||||
let content_size = replaced
|
||||
.used_size_as_if_inline_element(
|
||||
containing_block,
|
||||
style,
|
||||
&content_box_sizes_and_pbm,
|
||||
ignore_block_margins_for_stretch,
|
||||
)
|
||||
.to_physical_size(container_writing_mode);
|
||||
let fragments = replaced.make_fragments(layout_context, style, content_size);
|
||||
|
||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
|
||||
(fragments, content_rect, None, None)
|
||||
},
|
||||
IndependentFormattingContextContents::NonReplaced(non_replaced) => {
|
||||
let writing_mode = self.style().writing_mode;
|
||||
let available_inline_size =
|
||||
Au::zero().max(containing_block.size.inline - pbm_sums.inline_sum());
|
||||
let available_block_size = containing_block
|
||||
.size
|
||||
.block
|
||||
.to_definite()
|
||||
.map(|block_size| Au::zero().max(block_size - pbm_sums.block_sum()));
|
||||
let tentative_block_size = content_box_sizes_and_pbm
|
||||
.content_box_sizes
|
||||
.block
|
||||
.resolve_extrinsic(Size::FitContent, Au::zero(), available_block_size);
|
||||
|
||||
let get_content_size = || {
|
||||
let constraint_space = ConstraintSpace::new(
|
||||
tentative_block_size,
|
||||
writing_mode,
|
||||
non_replaced.preferred_aspect_ratio(),
|
||||
);
|
||||
self.inline_content_sizes(layout_context, &constraint_space)
|
||||
.sizes
|
||||
};
|
||||
|
||||
let is_table = layout_style.is_table();
|
||||
let inline_size = content_box_sizes_and_pbm.content_box_sizes.inline.resolve(
|
||||
Direction::Inline,
|
||||
Size::FitContent,
|
||||
Au::zero,
|
||||
Some(available_inline_size),
|
||||
get_content_size,
|
||||
is_table,
|
||||
);
|
||||
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
size: ContainingBlockSize {
|
||||
inline: inline_size,
|
||||
block: tentative_block_size,
|
||||
},
|
||||
style: self.style(),
|
||||
};
|
||||
assert_eq!(
|
||||
container_writing_mode.is_horizontal(),
|
||||
writing_mode.is_horizontal(),
|
||||
"Mixed horizontal and vertical writing modes are not supported yet"
|
||||
);
|
||||
|
||||
let lazy_block_size = LazySize::new(
|
||||
&content_box_sizes_and_pbm.content_box_sizes.block,
|
||||
Direction::Block,
|
||||
Size::FitContent,
|
||||
Au::zero,
|
||||
available_block_size,
|
||||
is_table,
|
||||
);
|
||||
|
||||
let independent_layout = non_replaced.layout(
|
||||
layout_context,
|
||||
child_positioning_context,
|
||||
&containing_block_for_children,
|
||||
containing_block,
|
||||
&self.base,
|
||||
false, /* depends_on_block_constraints */
|
||||
&lazy_block_size,
|
||||
);
|
||||
let inline_size = independent_layout
|
||||
.content_inline_size_for_table
|
||||
.unwrap_or(inline_size);
|
||||
let block_size = lazy_block_size.resolve(|| independent_layout.content_block_size);
|
||||
|
||||
let content_size = LogicalVec2 {
|
||||
block: block_size,
|
||||
inline: inline_size,
|
||||
}
|
||||
.to_physical_size(container_writing_mode);
|
||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
|
||||
|
||||
(
|
||||
independent_layout.fragments,
|
||||
content_rect,
|
||||
Some(independent_layout.baselines),
|
||||
independent_layout.specific_layout_info,
|
||||
)
|
||||
},
|
||||
let tentative_block_content_size =
|
||||
self.tentative_block_content_size(preferred_aspect_ratio);
|
||||
let tentative_block_size = if let Some(block_content_size) = tentative_block_content_size {
|
||||
SizeConstraint::Definite(content_box_sizes_and_pbm.content_box_sizes.block.resolve(
|
||||
Direction::Block,
|
||||
Size::FitContent,
|
||||
Au::zero,
|
||||
available_block_size,
|
||||
|| block_content_size,
|
||||
is_table,
|
||||
))
|
||||
} else {
|
||||
content_box_sizes_and_pbm
|
||||
.content_box_sizes
|
||||
.block
|
||||
.resolve_extrinsic(Size::FitContent, Au::zero(), available_block_size)
|
||||
};
|
||||
|
||||
let get_content_size = || {
|
||||
let constraint_space =
|
||||
ConstraintSpace::new(tentative_block_size, writing_mode, preferred_aspect_ratio);
|
||||
self.inline_content_sizes(layout_context, &constraint_space)
|
||||
.sizes
|
||||
};
|
||||
|
||||
let inline_size = content_box_sizes_and_pbm.content_box_sizes.inline.resolve(
|
||||
Direction::Inline,
|
||||
Size::FitContent,
|
||||
Au::zero,
|
||||
Some(available_inline_size),
|
||||
get_content_size,
|
||||
is_table,
|
||||
);
|
||||
|
||||
let containing_block_for_children = ContainingBlock {
|
||||
size: ContainingBlockSize {
|
||||
inline: inline_size,
|
||||
block: tentative_block_size,
|
||||
},
|
||||
style,
|
||||
};
|
||||
assert_eq!(
|
||||
container_writing_mode.is_horizontal(),
|
||||
writing_mode.is_horizontal(),
|
||||
"Mixed horizontal and vertical writing modes are not supported yet"
|
||||
);
|
||||
|
||||
let lazy_block_size = LazySize::new(
|
||||
&content_box_sizes_and_pbm.content_box_sizes.block,
|
||||
Direction::Block,
|
||||
Size::FitContent,
|
||||
Au::zero,
|
||||
available_block_size,
|
||||
is_table,
|
||||
);
|
||||
|
||||
let CacheableLayoutResult {
|
||||
content_inline_size_for_table,
|
||||
content_block_size,
|
||||
fragments,
|
||||
baselines,
|
||||
specific_layout_info,
|
||||
..
|
||||
} = self.layout(
|
||||
layout_context,
|
||||
child_positioning_context,
|
||||
&containing_block_for_children,
|
||||
containing_block,
|
||||
preferred_aspect_ratio,
|
||||
false, /* depends_on_block_constraints */
|
||||
&lazy_block_size,
|
||||
);
|
||||
|
||||
let content_size = LogicalVec2 {
|
||||
inline: content_inline_size_for_table.unwrap_or(inline_size),
|
||||
block: lazy_block_size.resolve(|| content_block_size),
|
||||
}
|
||||
.to_physical_size(container_writing_mode);
|
||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
|
||||
|
||||
let mut base_fragment_info = self.base_fragment_info();
|
||||
if content_box_sizes_and_pbm.depends_on_block_constraints {
|
||||
base_fragment_info.flags.insert(
|
||||
|
@ -2366,7 +2349,7 @@ impl IndependentFormattingContext {
|
|||
// And atomic inlines don't have clearance.
|
||||
let fragment = BoxFragment::new(
|
||||
base_fragment_info,
|
||||
self.style().clone(),
|
||||
style.clone(),
|
||||
fragments,
|
||||
content_rect,
|
||||
pbm.padding.to_physical(container_writing_mode),
|
||||
|
|
|
@ -85,13 +85,6 @@ impl<T: Copy> From<T> for LogicalVec2<T> {
|
|||
}
|
||||
|
||||
impl<T> LogicalVec2<T> {
|
||||
pub(crate) fn as_ref(&self) -> LogicalVec2<&T> {
|
||||
LogicalVec2 {
|
||||
inline: &self.inline,
|
||||
block: &self.block,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_inline_and_block_axes<U>(
|
||||
&self,
|
||||
inline_f: impl FnOnce(&T) -> U,
|
||||
|
|
|
@ -29,12 +29,10 @@ use crate::dom::NodeExt;
|
|||
use crate::fragment_tree::{
|
||||
BaseFragmentInfo, CollapsedBlockMargins, Fragment, IFrameFragment, ImageFragment,
|
||||
};
|
||||
use crate::geom::{
|
||||
LazySize, LogicalSides1D, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes,
|
||||
};
|
||||
use crate::geom::{LazySize, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes};
|
||||
use crate::layout_box_base::{CacheableLayoutResult, LayoutBoxBase};
|
||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM, LayoutStyle};
|
||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, LayoutStyle};
|
||||
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
||||
|
||||
#[derive(Debug, MallocSizeOf)]
|
||||
|
@ -410,29 +408,6 @@ impl ReplacedContents {
|
|||
})
|
||||
}
|
||||
|
||||
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width>
|
||||
/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height>
|
||||
///
|
||||
/// Also used in other cases, for example
|
||||
/// <https://drafts.csswg.org/css2/visudet.html#block-replaced-width>
|
||||
pub(crate) fn used_size_as_if_inline_element(
|
||||
&self,
|
||||
containing_block: &ContainingBlock,
|
||||
style: &ComputedValues,
|
||||
content_box_sizes_and_pbm: &ContentBoxSizesAndPBM,
|
||||
ignore_block_margins_for_stretch: LogicalSides1D<bool>,
|
||||
) -> LogicalVec2<Au> {
|
||||
let pbm = &content_box_sizes_and_pbm.pbm;
|
||||
self.used_size_as_if_inline_element_from_content_box_sizes(
|
||||
containing_block,
|
||||
style,
|
||||
self.preferred_aspect_ratio(style, &pbm.padding_border_sums),
|
||||
content_box_sizes_and_pbm.content_box_sizes.as_ref(),
|
||||
Size::FitContent.into(),
|
||||
pbm.sums_auto_is_zero(ignore_block_margins_for_stretch),
|
||||
)
|
||||
}
|
||||
|
||||
/// The aspect ratio of the default object sizes.
|
||||
/// <https://drafts.csswg.org/css-images-3/#default-object-size>
|
||||
pub(crate) fn default_aspect_ratio() -> AspectRatio {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue