mirror of
https://github.com/servo/servo.git
synced 2025-07-16 11:53:39 +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
|
.content_rect
|
||||||
.translate(pbm_physical_offset.to_vector());
|
.translate(pbm_physical_offset.to_vector());
|
||||||
|
|
||||||
// Apply baselines if necessary.
|
// Apply baselines.
|
||||||
let mut fragment = match baselines {
|
fragment = fragment.with_baselines(baselines);
|
||||||
Some(baselines) => fragment.with_baselines(baselines),
|
|
||||||
None => fragment,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Lay out absolutely positioned children if this new atomic establishes a containing block
|
// Lay out absolutely positioned children if this new atomic establishes a containing block
|
||||||
// for absolutes.
|
// for absolutes.
|
||||||
|
|
|
@ -2226,7 +2226,7 @@ fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &Containi
|
||||||
|
|
||||||
pub(crate) struct IndependentFloatOrAtomicLayoutResult {
|
pub(crate) struct IndependentFloatOrAtomicLayoutResult {
|
||||||
pub fragment: BoxFragment,
|
pub fragment: BoxFragment,
|
||||||
pub baselines: Option<Baselines>,
|
pub baselines: Baselines,
|
||||||
pub pbm_sums: LogicalSides<Au>,
|
pub pbm_sums: LogicalSides<Au>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2238,6 +2238,7 @@ impl IndependentFormattingContext {
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
) -> IndependentFloatOrAtomicLayoutResult {
|
) -> IndependentFloatOrAtomicLayoutResult {
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
|
let writing_mode = style.writing_mode;
|
||||||
let container_writing_mode = containing_block.style.writing_mode;
|
let container_writing_mode = containing_block.style.writing_mode;
|
||||||
let layout_style = self.layout_style();
|
let layout_style = self.layout_style();
|
||||||
let content_box_sizes_and_pbm =
|
let content_box_sizes_and_pbm =
|
||||||
|
@ -2245,115 +2246,97 @@ impl IndependentFormattingContext {
|
||||||
let pbm = &content_box_sizes_and_pbm.pbm;
|
let pbm = &content_box_sizes_and_pbm.pbm;
|
||||||
let margin = pbm.margin.auto_is(Au::zero);
|
let margin = pbm.margin.auto_is(Au::zero);
|
||||||
let pbm_sums = pbm.padding + pbm.border + margin;
|
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 {
|
let available_inline_size =
|
||||||
IndependentFormattingContextContents::Replaced(replaced) => {
|
Au::zero().max(containing_block.size.inline - pbm_sums.inline_sum());
|
||||||
// Floats and atomic inlines can't collapse margins with their parent,
|
let available_block_size = containing_block
|
||||||
// so don't ignore block margins when resolving a stretch block size.
|
.size
|
||||||
// https://drafts.csswg.org/css-sizing-4/#stretch-fit-sizing
|
.block
|
||||||
let ignore_block_margins_for_stretch = LogicalSides1D::new(false, false);
|
.to_definite()
|
||||||
|
.map(|block_size| Au::zero().max(block_size - pbm_sums.block_sum()));
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#float-replaced-width
|
let tentative_block_content_size =
|
||||||
// https://drafts.csswg.org/css2/visudet.html#inline-replaced-height
|
self.tentative_block_content_size(preferred_aspect_ratio);
|
||||||
let content_size = replaced
|
let tentative_block_size = if let Some(block_content_size) = tentative_block_content_size {
|
||||||
.used_size_as_if_inline_element(
|
SizeConstraint::Definite(content_box_sizes_and_pbm.content_box_sizes.block.resolve(
|
||||||
containing_block,
|
Direction::Block,
|
||||||
style,
|
Size::FitContent,
|
||||||
&content_box_sizes_and_pbm,
|
Au::zero,
|
||||||
ignore_block_margins_for_stretch,
|
available_block_size,
|
||||||
)
|
|| block_content_size,
|
||||||
.to_physical_size(container_writing_mode);
|
is_table,
|
||||||
let fragments = replaced.make_fragments(layout_context, style, content_size);
|
))
|
||||||
|
} else {
|
||||||
let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size);
|
content_box_sizes_and_pbm
|
||||||
(fragments, content_rect, None, None)
|
.content_box_sizes
|
||||||
},
|
.block
|
||||||
IndependentFormattingContextContents::NonReplaced(non_replaced) => {
|
.resolve_extrinsic(Size::FitContent, Au::zero(), available_block_size)
|
||||||
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 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();
|
let mut base_fragment_info = self.base_fragment_info();
|
||||||
if content_box_sizes_and_pbm.depends_on_block_constraints {
|
if content_box_sizes_and_pbm.depends_on_block_constraints {
|
||||||
base_fragment_info.flags.insert(
|
base_fragment_info.flags.insert(
|
||||||
|
@ -2366,7 +2349,7 @@ impl IndependentFormattingContext {
|
||||||
// And atomic inlines don't have clearance.
|
// And atomic inlines don't have clearance.
|
||||||
let fragment = BoxFragment::new(
|
let fragment = BoxFragment::new(
|
||||||
base_fragment_info,
|
base_fragment_info,
|
||||||
self.style().clone(),
|
style.clone(),
|
||||||
fragments,
|
fragments,
|
||||||
content_rect,
|
content_rect,
|
||||||
pbm.padding.to_physical(container_writing_mode),
|
pbm.padding.to_physical(container_writing_mode),
|
||||||
|
|
|
@ -85,13 +85,6 @@ impl<T: Copy> From<T> for LogicalVec2<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> 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>(
|
pub fn map_inline_and_block_axes<U>(
|
||||||
&self,
|
&self,
|
||||||
inline_f: impl FnOnce(&T) -> U,
|
inline_f: impl FnOnce(&T) -> U,
|
||||||
|
|
|
@ -29,12 +29,10 @@ use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::{
|
use crate::fragment_tree::{
|
||||||
BaseFragmentInfo, CollapsedBlockMargins, Fragment, IFrameFragment, ImageFragment,
|
BaseFragmentInfo, CollapsedBlockMargins, Fragment, IFrameFragment, ImageFragment,
|
||||||
};
|
};
|
||||||
use crate::geom::{
|
use crate::geom::{LazySize, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes};
|
||||||
LazySize, LogicalSides1D, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes,
|
|
||||||
};
|
|
||||||
use crate::layout_box_base::{CacheableLayoutResult, LayoutBoxBase};
|
use crate::layout_box_base::{CacheableLayoutResult, LayoutBoxBase};
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
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};
|
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
||||||
|
|
||||||
#[derive(Debug, MallocSizeOf)]
|
#[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.
|
/// The aspect ratio of the default object sizes.
|
||||||
/// <https://drafts.csswg.org/css-images-3/#default-object-size>
|
/// <https://drafts.csswg.org/css-images-3/#default-object-size>
|
||||||
pub(crate) fn default_aspect_ratio() -> AspectRatio {
|
pub(crate) fn default_aspect_ratio() -> AspectRatio {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue