mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Refactor box size computation (#34671)
in each layout logic, in order to correctly resolve sizing keywords. This patch adds a new `Sizes` struct which holds the preferred, min and max sizing values for one axis, and unifies the logic to resolve the final size into there. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
28e330c9b6
commit
e2a0ac07ff
8 changed files with 311 additions and 343 deletions
|
@ -34,7 +34,7 @@ use crate::formatting_contexts::{
|
||||||
Baselines, IndependentFormattingContextContents, IndependentLayout,
|
Baselines, IndependentFormattingContextContents, IndependentLayout,
|
||||||
};
|
};
|
||||||
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags};
|
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags};
|
||||||
use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, Size};
|
use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, Size, Sizes};
|
||||||
use crate::positioned::{
|
use crate::positioned::{
|
||||||
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
relative_adjustement, AbsolutelyPositionedBox, PositioningContext, PositioningContextLength,
|
||||||
};
|
};
|
||||||
|
@ -1957,20 +1957,22 @@ impl FlexItem<'_> {
|
||||||
let item_style = independent_formatting_context.style();
|
let item_style = independent_formatting_context.style();
|
||||||
match &independent_formatting_context.contents {
|
match &independent_formatting_context.contents {
|
||||||
IndependentFormattingContextContents::Replaced(replaced) => {
|
IndependentFormattingContextContents::Replaced(replaced) => {
|
||||||
|
let min_size = flex_axis.vec2_to_flow_relative(self.content_min_size);
|
||||||
|
let max_size = flex_axis.vec2_to_flow_relative(self.content_max_size);
|
||||||
let size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
|
let size = replaced.used_size_as_if_inline_element_from_content_box_sizes(
|
||||||
containing_block,
|
containing_block,
|
||||||
item_style,
|
item_style,
|
||||||
self.preferred_aspect_ratio,
|
self.preferred_aspect_ratio,
|
||||||
LogicalVec2 {
|
&Sizes::new(
|
||||||
inline: Size::Numeric(inline_size),
|
block_size.non_auto().map_or(Size::Initial, Size::Numeric),
|
||||||
block: block_size.non_auto().map_or(Size::Initial, Size::Numeric),
|
Size::Numeric(min_size.block),
|
||||||
},
|
max_size.block.map_or(Size::Initial, Size::Numeric),
|
||||||
flex_axis
|
),
|
||||||
.vec2_to_flow_relative(self.content_min_size)
|
&Sizes::new(
|
||||||
.map(|size| Size::Numeric(*size)),
|
Size::Numeric(inline_size),
|
||||||
flex_axis
|
Size::Numeric(min_size.inline),
|
||||||
.vec2_to_flow_relative(self.content_max_size)
|
max_size.inline.map_or(Size::Initial, Size::Numeric),
|
||||||
.map(|size| size.map_or(Size::Initial, Size::Numeric)),
|
),
|
||||||
flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero),
|
flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero),
|
||||||
);
|
);
|
||||||
let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross;
|
let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross;
|
||||||
|
@ -2777,10 +2779,22 @@ impl FlexItemBox {
|
||||||
flex_context.containing_block,
|
flex_context.containing_block,
|
||||||
style,
|
style,
|
||||||
preferred_aspect_ratio,
|
preferred_aspect_ratio,
|
||||||
content_box_size
|
&Sizes::new(
|
||||||
.map(|size| size.non_auto().map_or(Size::Initial, Size::Numeric)),
|
content_box_size
|
||||||
min_size.map(|size| Size::Numeric(*size)),
|
.block
|
||||||
max_size.map(|size| size.map_or(Size::Initial, Size::Numeric)),
|
.non_auto()
|
||||||
|
.map_or(Size::Initial, Size::Numeric),
|
||||||
|
Size::Numeric(min_size.block),
|
||||||
|
max_size.block.map_or(Size::Initial, Size::Numeric),
|
||||||
|
),
|
||||||
|
&Sizes::new(
|
||||||
|
content_box_size
|
||||||
|
.inline
|
||||||
|
.non_auto()
|
||||||
|
.map_or(Size::Initial, Size::Numeric),
|
||||||
|
Size::Numeric(min_size.inline),
|
||||||
|
max_size.inline.map_or(Size::Initial, Size::Numeric),
|
||||||
|
),
|
||||||
padding_border_margin.padding_border_sums +
|
padding_border_margin.padding_border_sums +
|
||||||
padding_border_margin.margin.auto_is(Au::zero).sum(),
|
padding_border_margin.margin.auto_is(Au::zero).sum(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
//! Flow layout, also known as block-and-inline layout.
|
//! Flow layout, also known as block-and-inline layout.
|
||||||
|
|
||||||
use std::cell::LazyCell;
|
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use inline::InlineFormattingContext;
|
use inline::InlineFormattingContext;
|
||||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
@ -35,7 +33,7 @@ use crate::fragment_tree::{
|
||||||
};
|
};
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides,
|
AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides,
|
||||||
Size, ToLogical, ToLogicalWithContainingBlock,
|
Size, Sizes, ToLogical, ToLogicalWithContainingBlock,
|
||||||
};
|
};
|
||||||
use crate::layout_box_base::LayoutBoxBase;
|
use crate::layout_box_base::LayoutBoxBase;
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
|
@ -796,9 +794,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
|
||||||
let ContainingBlockPaddingAndBorder {
|
let ContainingBlockPaddingAndBorder {
|
||||||
containing_block: containing_block_for_children,
|
containing_block: containing_block_for_children,
|
||||||
pbm,
|
pbm,
|
||||||
preferred_block_size,
|
block_sizes,
|
||||||
min_block_size,
|
|
||||||
max_block_size,
|
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
available_block_size,
|
available_block_size,
|
||||||
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
||||||
|
@ -939,16 +935,12 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
|
||||||
content_block_size += collapsible_margins_in_children.end.solve();
|
content_block_size += collapsible_margins_in_children.end.solve();
|
||||||
}
|
}
|
||||||
|
|
||||||
let available_block_size = available_block_size.unwrap_or(content_block_size);
|
let block_size = block_sizes.resolve(
|
||||||
let block_content_sizes = LazyCell::new(|| content_block_size.into());
|
Size::FitContent,
|
||||||
let preferred_block_size =
|
Au::zero(),
|
||||||
preferred_block_size.resolve(Size::FitContent, available_block_size, &block_content_sizes);
|
available_block_size.unwrap_or(content_block_size),
|
||||||
let min_block_size = min_block_size
|
|| content_block_size.into(),
|
||||||
.resolve_non_initial(available_block_size, &block_content_sizes)
|
);
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block_size =
|
|
||||||
max_block_size.resolve_non_initial(available_block_size, &block_content_sizes);
|
|
||||||
let block_size = preferred_block_size.clamp_between_extremums(min_block_size, max_block_size);
|
|
||||||
|
|
||||||
if let Some(ref mut sequential_layout_state) = sequential_layout_state {
|
if let Some(ref mut sequential_layout_state) = sequential_layout_state {
|
||||||
// Now that we're done laying out our children, we can restore the
|
// Now that we're done laying out our children, we can restore the
|
||||||
|
@ -1042,9 +1034,7 @@ impl IndependentNonReplacedContents {
|
||||||
let ContainingBlockPaddingAndBorder {
|
let ContainingBlockPaddingAndBorder {
|
||||||
containing_block: containing_block_for_children,
|
containing_block: containing_block_for_children,
|
||||||
pbm,
|
pbm,
|
||||||
preferred_block_size,
|
block_sizes,
|
||||||
min_block_size,
|
|
||||||
max_block_size,
|
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
available_block_size,
|
available_block_size,
|
||||||
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
} = solve_containing_block_padding_and_border_for_in_flow_box(
|
||||||
|
@ -1063,21 +1053,12 @@ impl IndependentNonReplacedContents {
|
||||||
let (block_size, inline_size) = match layout.content_inline_size_for_table {
|
let (block_size, inline_size) = match layout.content_inline_size_for_table {
|
||||||
Some(inline_size) => (layout.content_block_size, inline_size),
|
Some(inline_size) => (layout.content_block_size, inline_size),
|
||||||
None => {
|
None => {
|
||||||
let available_block_size =
|
let block_size = block_sizes.resolve(
|
||||||
available_block_size.unwrap_or(layout.content_block_size);
|
|
||||||
let block_content_sizes = LazyCell::new(|| layout.content_block_size.into());
|
|
||||||
let preferred_block_size = preferred_block_size.resolve(
|
|
||||||
Size::FitContent,
|
Size::FitContent,
|
||||||
available_block_size,
|
Au::zero(),
|
||||||
&block_content_sizes,
|
available_block_size.unwrap_or(layout.content_block_size),
|
||||||
|
|| layout.content_block_size.into(),
|
||||||
);
|
);
|
||||||
let min_block_size = min_block_size
|
|
||||||
.resolve_non_initial(available_block_size, &block_content_sizes)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block_size =
|
|
||||||
max_block_size.resolve_non_initial(available_block_size, &block_content_sizes);
|
|
||||||
let block_size =
|
|
||||||
preferred_block_size.clamp_between_extremums(min_block_size, max_block_size);
|
|
||||||
(block_size, containing_block_for_children.size.inline)
|
(block_size, containing_block_for_children.size.inline)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1137,9 +1118,7 @@ impl IndependentNonReplacedContents {
|
||||||
let style = &base.style;
|
let style = &base.style;
|
||||||
let containing_block_writing_mode = containing_block.style.writing_mode;
|
let containing_block_writing_mode = containing_block.style.writing_mode;
|
||||||
let ContentBoxSizesAndPBM {
|
let ContentBoxSizesAndPBM {
|
||||||
content_box_size,
|
content_box_sizes,
|
||||||
content_min_box_size,
|
|
||||||
content_max_box_size,
|
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
|
@ -1181,21 +1160,14 @@ impl IndependentNonReplacedContents {
|
||||||
.block
|
.block
|
||||||
.non_auto()
|
.non_auto()
|
||||||
.map(|block_size| Au::zero().max(block_size - pbm_sums.block_sum()));
|
.map(|block_size| Au::zero().max(block_size - pbm_sums.block_sum()));
|
||||||
let preferred_block_size = content_box_size
|
let (preferred_block_size, min_block_size, max_block_size) = content_box_sizes
|
||||||
.block
|
.block
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
.resolve_each_extrinsic(Size::FitContent, Au::zero(), available_block_size);
|
||||||
let min_block_size = content_min_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block_size = content_max_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
|
||||||
let tentative_block_size =
|
let tentative_block_size =
|
||||||
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
||||||
|
|
||||||
// With the tentative block size we can compute the inline min/max-content sizes.
|
// With the tentative block size we can compute the inline min/max-content sizes.
|
||||||
let inline_content_sizes = LazyCell::new(|| {
|
let get_inline_content_sizes = || {
|
||||||
let constraint_space = ConstraintSpace::new(
|
let constraint_space = ConstraintSpace::new(
|
||||||
tentative_block_size,
|
tentative_block_size,
|
||||||
style.writing_mode,
|
style.writing_mode,
|
||||||
|
@ -1203,55 +1175,29 @@ impl IndependentNonReplacedContents {
|
||||||
);
|
);
|
||||||
base.inline_content_sizes(layout_context, &constraint_space, self)
|
base.inline_content_sizes(layout_context, &constraint_space, self)
|
||||||
.sizes
|
.sizes
|
||||||
});
|
};
|
||||||
|
|
||||||
// The final inline size can depend on the available space, which depends on where
|
|
||||||
// we are placing the box, since floats reduce the available space.
|
|
||||||
// TODO: this logic could be refined further, since even if some of the 3 sizes
|
|
||||||
// depends on the available space, the resulting size might not. For example,
|
|
||||||
// `min-width: 200px; width: 100px; max-width: stretch`.
|
|
||||||
let inline_size_depends_on_available_space = matches!(
|
|
||||||
content_box_size.inline,
|
|
||||||
Size::Initial | Size::Stretch | Size::FitContent
|
|
||||||
) || matches!(
|
|
||||||
content_min_box_size.inline,
|
|
||||||
Size::Stretch | Size::FitContent
|
|
||||||
) || matches!(
|
|
||||||
content_max_box_size.inline,
|
|
||||||
Size::Stretch | Size::FitContent
|
|
||||||
);
|
|
||||||
let compute_inline_size = |stretch_size| {
|
let compute_inline_size = |stretch_size| {
|
||||||
let preferred_inline_size =
|
content_box_sizes.inline.resolve(
|
||||||
content_box_size
|
Size::Stretch,
|
||||||
.inline
|
Au::zero(),
|
||||||
.resolve(Size::Stretch, stretch_size, &inline_content_sizes);
|
stretch_size,
|
||||||
let min_inline_size = content_min_box_size
|
get_inline_content_sizes,
|
||||||
.inline
|
)
|
||||||
.resolve_non_initial(stretch_size, &inline_content_sizes)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_inline_size = content_max_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(stretch_size, &inline_content_sizes);
|
|
||||||
preferred_inline_size.clamp_between_extremums(min_inline_size, max_inline_size)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let compute_block_size = |layout: &IndependentLayout| {
|
let compute_block_size = |layout: &IndependentLayout| {
|
||||||
let stretch_size = available_block_size.unwrap_or(layout.content_block_size);
|
content_box_sizes.block.resolve(
|
||||||
let block_contents_size = LazyCell::new(|| layout.content_block_size.into());
|
Size::FitContent,
|
||||||
let min_block_size = content_min_box_size
|
Au::zero(),
|
||||||
.block
|
available_block_size.unwrap_or(layout.content_block_size),
|
||||||
.resolve_non_initial(stretch_size, &block_contents_size)
|
|| layout.content_block_size.into(),
|
||||||
.unwrap_or_default();
|
)
|
||||||
let max_block_size = content_max_box_size
|
|
||||||
.block
|
|
||||||
.resolve_non_initial(stretch_size, &block_contents_size);
|
|
||||||
tentative_block_size
|
|
||||||
.to_definite()
|
|
||||||
.unwrap_or(layout.content_block_size)
|
|
||||||
.clamp_between_extremums(min_block_size, max_block_size)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !inline_size_depends_on_available_space {
|
// The final inline size can depend on the available space, which depends on where
|
||||||
|
// we are placing the box, since floats reduce the available space.
|
||||||
|
if !content_box_sizes.inline.depends_on_available_space() {
|
||||||
// If the inline size doesn't depend on the available inline space, we can just
|
// If the inline size doesn't depend on the available inline space, we can just
|
||||||
// compute it with an available inline space of zero. Then, after layout we can
|
// compute it with an available inline space of zero. Then, after layout we can
|
||||||
// compute the block size, and finally place among floats.
|
// compute the block size, and finally place among floats.
|
||||||
|
@ -1591,9 +1537,7 @@ impl ReplacedContents {
|
||||||
struct ContainingBlockPaddingAndBorder<'a> {
|
struct ContainingBlockPaddingAndBorder<'a> {
|
||||||
containing_block: ContainingBlock<'a>,
|
containing_block: ContainingBlock<'a>,
|
||||||
pbm: PaddingBorderMargin,
|
pbm: PaddingBorderMargin,
|
||||||
preferred_block_size: Size<Au>,
|
block_sizes: Sizes,
|
||||||
min_block_size: Size<Au>,
|
|
||||||
max_block_size: Size<Au>,
|
|
||||||
depends_on_block_constraints: bool,
|
depends_on_block_constraints: bool,
|
||||||
available_block_size: Option<Au>,
|
available_block_size: Option<Au>,
|
||||||
}
|
}
|
||||||
|
@ -1637,9 +1581,7 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
return ContainingBlockPaddingAndBorder {
|
return ContainingBlockPaddingAndBorder {
|
||||||
containing_block: containing_block_for_children,
|
containing_block: containing_block_for_children,
|
||||||
pbm: PaddingBorderMargin::zero(),
|
pbm: PaddingBorderMargin::zero(),
|
||||||
preferred_block_size: Size::default(),
|
block_sizes: Sizes::default(),
|
||||||
min_block_size: Size::default(),
|
|
||||||
max_block_size: Size::default(),
|
|
||||||
depends_on_block_constraints: false,
|
depends_on_block_constraints: false,
|
||||||
// The available block size may actually be definite, but it should be irrelevant
|
// The available block size may actually be definite, but it should be irrelevant
|
||||||
// since the sizing properties are set to their initial value.
|
// since the sizing properties are set to their initial value.
|
||||||
|
@ -1648,9 +1590,7 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let ContentBoxSizesAndPBM {
|
let ContentBoxSizesAndPBM {
|
||||||
content_box_size,
|
content_box_sizes,
|
||||||
content_min_box_size,
|
|
||||||
content_max_box_size,
|
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
|
@ -1668,42 +1608,27 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/#the-height-property
|
// https://drafts.csswg.org/css2/#the-height-property
|
||||||
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
|
// https://drafts.csswg.org/css2/visudet.html#min-max-heights
|
||||||
let preferred_block_size = content_box_size
|
let tentative_block_size = content_box_sizes.block.resolve_extrinsic(
|
||||||
.block
|
Size::FitContent,
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
Au::zero(),
|
||||||
let min_block_size = content_min_box_size
|
available_block_size,
|
||||||
.block
|
);
|
||||||
.maybe_resolve_extrinsic(available_block_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block_size = content_max_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
|
||||||
let tentative_block_size =
|
|
||||||
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/#the-width-property
|
// https://drafts.csswg.org/css2/#the-width-property
|
||||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
||||||
let inline_content_sizes = LazyCell::new(|| {
|
let get_inline_content_sizes = || {
|
||||||
get_inline_content_sizes(&ConstraintSpace::new(
|
get_inline_content_sizes(&ConstraintSpace::new(
|
||||||
tentative_block_size,
|
tentative_block_size,
|
||||||
writing_mode,
|
writing_mode,
|
||||||
None, /* TODO: support preferred aspect ratios on non-replaced boxes */
|
None, /* TODO: support preferred aspect ratios on non-replaced boxes */
|
||||||
))
|
))
|
||||||
});
|
};
|
||||||
let preferred_inline_size = content_box_size.inline.resolve(
|
let inline_size = content_box_sizes.inline.resolve(
|
||||||
Size::Stretch,
|
Size::Stretch,
|
||||||
|
Au::zero(),
|
||||||
available_inline_size,
|
available_inline_size,
|
||||||
&inline_content_sizes,
|
get_inline_content_sizes,
|
||||||
);
|
);
|
||||||
let min_inline_size = content_min_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(available_inline_size, &inline_content_sizes)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_inline_size = content_max_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(available_inline_size, &inline_content_sizes);
|
|
||||||
let inline_size =
|
|
||||||
preferred_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
|
|
||||||
|
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
size: ContainingBlockSize {
|
size: ContainingBlockSize {
|
||||||
|
@ -1724,9 +1649,7 @@ fn solve_containing_block_padding_and_border_for_in_flow_box<'a>(
|
||||||
ContainingBlockPaddingAndBorder {
|
ContainingBlockPaddingAndBorder {
|
||||||
containing_block: containing_block_for_children,
|
containing_block: containing_block_for_children,
|
||||||
pbm,
|
pbm,
|
||||||
preferred_block_size: content_box_size.block,
|
block_sizes: content_box_sizes.block,
|
||||||
min_block_size: content_min_box_size.block,
|
|
||||||
max_block_size: content_max_box_size.block,
|
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
available_block_size,
|
available_block_size,
|
||||||
}
|
}
|
||||||
|
@ -2182,23 +2105,12 @@ impl IndependentFormattingContext {
|
||||||
.block
|
.block
|
||||||
.non_auto()
|
.non_auto()
|
||||||
.map(|block_size| (block_size - pbm_sums.block_sum()).max(Au::zero()));
|
.map(|block_size| (block_size - pbm_sums.block_sum()).max(Au::zero()));
|
||||||
let preferred_block_size = content_box_sizes_and_pbm
|
let tentative_block_size = content_box_sizes_and_pbm
|
||||||
.content_box_size
|
.content_box_sizes
|
||||||
.block
|
.block
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
.resolve_extrinsic(Size::FitContent, Au::zero(), available_block_size);
|
||||||
let min_block_size = content_box_sizes_and_pbm
|
|
||||||
.content_min_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block_size = content_box_sizes_and_pbm
|
|
||||||
.content_max_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
|
||||||
let tentative_block_size =
|
|
||||||
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size);
|
|
||||||
|
|
||||||
let content_size = LazyCell::new(|| {
|
let get_content_size = || {
|
||||||
let constraint_space = ConstraintSpace::new(
|
let constraint_space = ConstraintSpace::new(
|
||||||
tentative_block_size,
|
tentative_block_size,
|
||||||
writing_mode,
|
writing_mode,
|
||||||
|
@ -2206,29 +2118,14 @@ impl IndependentFormattingContext {
|
||||||
);
|
);
|
||||||
self.inline_content_sizes(layout_context, &constraint_space)
|
self.inline_content_sizes(layout_context, &constraint_space)
|
||||||
.sizes
|
.sizes
|
||||||
});
|
};
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#float-width
|
let inline_size = content_box_sizes_and_pbm.content_box_sizes.inline.resolve(
|
||||||
// https://drafts.csswg.org/css2/visudet.html#inlineblock-width
|
Size::FitContent,
|
||||||
let tentative_inline_size = content_box_sizes_and_pbm
|
Au::zero(),
|
||||||
.content_box_size
|
available_inline_size,
|
||||||
.inline
|
get_content_size,
|
||||||
.resolve(Size::FitContent, available_inline_size, &content_size);
|
);
|
||||||
|
|
||||||
// https://drafts.csswg.org/css2/visudet.html#min-max-widths
|
|
||||||
// In this case “applying the rules above again” with a non-auto inline-size
|
|
||||||
// always results in that size.
|
|
||||||
let min_inline_size = content_box_sizes_and_pbm
|
|
||||||
.content_min_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(available_inline_size, &content_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_inline_size = content_box_sizes_and_pbm
|
|
||||||
.content_max_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(available_inline_size, &content_size);
|
|
||||||
let inline_size =
|
|
||||||
tentative_inline_size.clamp_between_extremums(min_inline_size, max_inline_size);
|
|
||||||
|
|
||||||
let containing_block_for_children = ContainingBlock {
|
let containing_block_for_children = ContainingBlock {
|
||||||
size: ContainingBlockSize {
|
size: ContainingBlockSize {
|
||||||
|
@ -2249,31 +2146,21 @@ impl IndependentFormattingContext {
|
||||||
&containing_block_for_children,
|
&containing_block_for_children,
|
||||||
containing_block,
|
containing_block,
|
||||||
);
|
);
|
||||||
let (inline_size, block_size) =
|
let (inline_size, block_size) = match independent_layout
|
||||||
match independent_layout.content_inline_size_for_table {
|
.content_inline_size_for_table
|
||||||
Some(inline) => (inline, independent_layout.content_block_size),
|
{
|
||||||
None => {
|
Some(inline) => (inline, independent_layout.content_block_size),
|
||||||
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
None => {
|
||||||
let stretch_size = available_block_size
|
// https://drafts.csswg.org/css2/visudet.html#block-root-margin
|
||||||
.unwrap_or(independent_layout.content_block_size);
|
let block_size = content_box_sizes_and_pbm.content_box_sizes.block.resolve(
|
||||||
let content_size =
|
Size::FitContent,
|
||||||
LazyCell::new(|| independent_layout.content_block_size.into());
|
Au::zero(),
|
||||||
let min_block_size = content_box_sizes_and_pbm
|
available_block_size.unwrap_or(independent_layout.content_block_size),
|
||||||
.content_min_box_size
|
|| independent_layout.content_block_size.into(),
|
||||||
.block
|
);
|
||||||
.resolve_non_initial(stretch_size, &content_size)
|
(inline_size, block_size)
|
||||||
.unwrap_or_default();
|
},
|
||||||
let max_block_size = content_box_sizes_and_pbm
|
};
|
||||||
.content_max_box_size
|
|
||||||
.block
|
|
||||||
.resolve_non_initial(stretch_size, &content_size);
|
|
||||||
let block_size = tentative_block_size
|
|
||||||
.to_definite()
|
|
||||||
.unwrap_or(independent_layout.content_block_size)
|
|
||||||
.clamp_between_extremums(min_block_size, max_block_size);
|
|
||||||
(inline_size, block_size)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let content_size = LogicalVec2 {
|
let content_size = LogicalVec2 {
|
||||||
block: block_size,
|
block: block_size,
|
||||||
|
|
|
@ -870,3 +870,122 @@ impl SizeConstraint {
|
||||||
.map_or(AutoOr::Auto, AutoOr::LengthPercentage)
|
.map_or(AutoOr::Auto, AutoOr::LengthPercentage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub(crate) struct Sizes {
|
||||||
|
/// <https://drafts.csswg.org/css-sizing-3/#preferred-size-properties>
|
||||||
|
pub preferred: Size<Au>,
|
||||||
|
/// <https://drafts.csswg.org/css-sizing-3/#min-size-properties>
|
||||||
|
pub min: Size<Au>,
|
||||||
|
/// <https://drafts.csswg.org/css-sizing-3/#max-size-properties>
|
||||||
|
pub max: Size<Au>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sizes {
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn new(preferred: Size<Au>, min: Size<Au>, max: Size<Au>) -> Self {
|
||||||
|
Self {
|
||||||
|
preferred,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn depends_on_available_space(&self) -> bool {
|
||||||
|
// TODO: this logic could be refined further, since even if some of the 3 sizes
|
||||||
|
// depends on the available space, the resulting size might not. For example,
|
||||||
|
// `min-width: 200px; width: 100px; max-width: stretch`.
|
||||||
|
matches!(
|
||||||
|
self.preferred,
|
||||||
|
Size::Initial | Size::Stretch | Size::FitContent
|
||||||
|
) || matches!(self.min, Size::Stretch | Size::FitContent) ||
|
||||||
|
matches!(self.max, Size::Stretch | Size::FitContent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves the three sizes into a single numerical value.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn resolve(
|
||||||
|
&self,
|
||||||
|
automatic_size: Size<Au>,
|
||||||
|
automatic_minimum_size: Au,
|
||||||
|
stretch_size: Au,
|
||||||
|
get_content_size: impl FnOnce() -> ContentSizes,
|
||||||
|
) -> Au {
|
||||||
|
let (preferred, min, max) = self.resolve_each(
|
||||||
|
automatic_size,
|
||||||
|
automatic_minimum_size,
|
||||||
|
stretch_size,
|
||||||
|
get_content_size,
|
||||||
|
);
|
||||||
|
preferred.clamp_between_extremums(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves each of the three sizes into a numerical value, separately.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn resolve_each(
|
||||||
|
&self,
|
||||||
|
automatic_size: Size<Au>,
|
||||||
|
automatic_minimum_size: Au,
|
||||||
|
stretch_size: Au,
|
||||||
|
get_content_size: impl FnOnce() -> ContentSizes,
|
||||||
|
) -> (Au, Au, Option<Au>) {
|
||||||
|
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
|
||||||
|
// A LazyCell will only invoke it once if needed, and then reuse the result.
|
||||||
|
let content_size = LazyCell::new(get_content_size);
|
||||||
|
(
|
||||||
|
self.preferred
|
||||||
|
.resolve(automatic_size, stretch_size, &content_size),
|
||||||
|
self.min
|
||||||
|
.resolve_non_initial(stretch_size, &content_size)
|
||||||
|
.unwrap_or(automatic_minimum_size),
|
||||||
|
self.max.resolve_non_initial(stretch_size, &content_size),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to extrinsically resolve the three sizes into a single [`SizeConstraint`].
|
||||||
|
/// Values that are intrinsic or need `stretch_size` when it's `None` are handled as such:
|
||||||
|
/// - On the preferred size, they make the returned value be an indefinite [`SizeConstraint::MinMax`].
|
||||||
|
/// - On the min size, they are treated as `auto`, enforcing the automatic minimum size.
|
||||||
|
/// - On the max size, they are treated as `none`, enforcing no maximum.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn resolve_extrinsic(
|
||||||
|
&self,
|
||||||
|
automatic_size: Size<Au>,
|
||||||
|
automatic_minimum_size: Au,
|
||||||
|
stretch_size: Option<Au>,
|
||||||
|
) -> SizeConstraint {
|
||||||
|
let (preferred, min, max) =
|
||||||
|
self.resolve_each_extrinsic(automatic_size, automatic_minimum_size, stretch_size);
|
||||||
|
SizeConstraint::new(preferred, min, max)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to extrinsically resolve each of the three sizes into a numerical value, separately.
|
||||||
|
/// This can't resolve values that are intrinsic or need `stretch_size` but it's `None`.
|
||||||
|
/// - The 1st returned value is the resolved preferred size. If it can't be resolved then
|
||||||
|
/// the returned value is `None`. Note that this is different than treating it as `auto`.
|
||||||
|
/// TODO: This needs to be discussed in <https://github.com/w3c/csswg-drafts/issues/11387>.
|
||||||
|
/// - The 2nd returned value is the resolved minimum size. If it can't be resolved then we
|
||||||
|
/// treat it as the initial `auto`, returning the automatic minimum size.
|
||||||
|
/// - The 3rd returned value is the resolved maximum size. If it can't be resolved then we
|
||||||
|
/// treat it as the initial `none`, returning `None`.
|
||||||
|
#[inline]
|
||||||
|
pub(crate) fn resolve_each_extrinsic(
|
||||||
|
&self,
|
||||||
|
automatic_size: Size<Au>,
|
||||||
|
automatic_minimum_size: Au,
|
||||||
|
stretch_size: Option<Au>,
|
||||||
|
) -> (Option<Au>, Au, Option<Au>) {
|
||||||
|
(
|
||||||
|
if self.preferred.is_initial() {
|
||||||
|
automatic_size.maybe_resolve_extrinsic(stretch_size)
|
||||||
|
} else {
|
||||||
|
self.preferred.maybe_resolve_extrinsic(stretch_size)
|
||||||
|
},
|
||||||
|
self.min
|
||||||
|
.maybe_resolve_extrinsic(stretch_size)
|
||||||
|
.unwrap_or(automatic_minimum_size),
|
||||||
|
self.max.maybe_resolve_extrinsic(stretch_size),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::cell::LazyCell;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -28,10 +27,10 @@ use crate::fragment_tree::{
|
||||||
};
|
};
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint,
|
AuOrAuto, LengthPercentageOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint,
|
||||||
PhysicalRect, PhysicalVec, Size, ToLogical, ToLogicalWithContainingBlock,
|
PhysicalRect, PhysicalVec, Size, Sizes, ToLogical, ToLogicalWithContainingBlock,
|
||||||
};
|
};
|
||||||
use crate::sizing::ContentSizes;
|
use crate::sizing::ContentSizes;
|
||||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
use crate::style_ext::{ComputedValuesExt, ContentBoxSizesAndPBM, DisplayInside};
|
||||||
use crate::{
|
use crate::{
|
||||||
ConstraintSpace, ContainingBlock, ContainingBlockSize, DefiniteContainingBlock, SizeConstraint,
|
ConstraintSpace, ContainingBlock, ContainingBlockSize, DefiniteContainingBlock, SizeConstraint,
|
||||||
};
|
};
|
||||||
|
@ -460,11 +459,12 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
let absolutely_positioned_box = self.absolutely_positioned_box.borrow();
|
let absolutely_positioned_box = self.absolutely_positioned_box.borrow();
|
||||||
let context = &absolutely_positioned_box.context;
|
let context = &absolutely_positioned_box.context;
|
||||||
let style = context.style().clone();
|
let style = context.style().clone();
|
||||||
|
let ContentBoxSizesAndPBM {
|
||||||
|
content_box_sizes,
|
||||||
|
pbm,
|
||||||
|
..
|
||||||
|
} = style.content_box_sizes_and_padding_border_margin(&containing_block.into());
|
||||||
let containing_block = &containing_block.into();
|
let containing_block = &containing_block.into();
|
||||||
let pbm = style.padding_border_margin(containing_block);
|
|
||||||
let computed_size = style.content_box_size(containing_block, &pbm);
|
|
||||||
let computed_min_size = style.content_min_box_size(containing_block, &pbm);
|
|
||||||
let computed_max_size = style.content_max_box_size(containing_block, &pbm);
|
|
||||||
|
|
||||||
let shared_fragment = self.fragment.borrow();
|
let shared_fragment = self.fragment.borrow();
|
||||||
let static_position_rect = shared_fragment
|
let static_position_rect = shared_fragment
|
||||||
|
@ -489,9 +489,7 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
padding_border_sum: pbm.padding_border_sums.inline,
|
padding_border_sum: pbm.padding_border_sums.inline,
|
||||||
computed_margin_start: pbm.margin.inline_start,
|
computed_margin_start: pbm.margin.inline_start,
|
||||||
computed_margin_end: pbm.margin.inline_end,
|
computed_margin_end: pbm.margin.inline_end,
|
||||||
computed_size: computed_size.inline,
|
computed_sizes: content_box_sizes.inline,
|
||||||
computed_min_size: computed_min_size.inline,
|
|
||||||
computed_max_size: computed_max_size.inline,
|
|
||||||
avoid_negative_margin_start: true,
|
avoid_negative_margin_start: true,
|
||||||
box_offsets: inline_box_offsets,
|
box_offsets: inline_box_offsets,
|
||||||
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Inline),
|
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Inline),
|
||||||
|
@ -515,9 +513,7 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
padding_border_sum: pbm.padding_border_sums.block,
|
padding_border_sum: pbm.padding_border_sums.block,
|
||||||
computed_margin_start: pbm.margin.block_start,
|
computed_margin_start: pbm.margin.block_start,
|
||||||
computed_margin_end: pbm.margin.block_end,
|
computed_margin_end: pbm.margin.block_end,
|
||||||
computed_size: computed_size.block,
|
computed_sizes: content_box_sizes.block,
|
||||||
computed_min_size: computed_min_size.block,
|
|
||||||
computed_max_size: computed_max_size.block,
|
|
||||||
avoid_negative_margin_start: false,
|
avoid_negative_margin_start: false,
|
||||||
box_offsets: block_box_offsets,
|
box_offsets: block_box_offsets,
|
||||||
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Block),
|
static_position_rect_axis: static_position_rect.get_axis(AxisDirection::Block),
|
||||||
|
@ -536,9 +532,8 @@ impl HoistedAbsolutelyPositionedBox {
|
||||||
containing_block,
|
containing_block,
|
||||||
&style,
|
&style,
|
||||||
context.preferred_aspect_ratio(&pbm.padding_border_sums),
|
context.preferred_aspect_ratio(&pbm.padding_border_sums),
|
||||||
computed_size,
|
&block_axis_solver.computed_sizes,
|
||||||
computed_min_size,
|
&inline_axis_solver.computed_sizes,
|
||||||
computed_max_size,
|
|
||||||
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
|
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums,
|
||||||
);
|
);
|
||||||
inline_axis_solver.override_size(used_size.inline);
|
inline_axis_solver.override_size(used_size.inline);
|
||||||
|
@ -746,9 +741,7 @@ struct AbsoluteAxisSolver<'a> {
|
||||||
padding_border_sum: Au,
|
padding_border_sum: Au,
|
||||||
computed_margin_start: AuOrAuto,
|
computed_margin_start: AuOrAuto,
|
||||||
computed_margin_end: AuOrAuto,
|
computed_margin_end: AuOrAuto,
|
||||||
computed_size: Size<Au>,
|
computed_sizes: Sizes,
|
||||||
computed_min_size: Size<Au>,
|
|
||||||
computed_max_size: Size<Au>,
|
|
||||||
avoid_negative_margin_start: bool,
|
avoid_negative_margin_start: bool,
|
||||||
box_offsets: AbsoluteBoxOffsets<'a>,
|
box_offsets: AbsoluteBoxOffsets<'a>,
|
||||||
static_position_rect_axis: RectAxis,
|
static_position_rect_axis: RectAxis,
|
||||||
|
@ -795,40 +788,21 @@ impl<'a> AbsoluteAxisSolver<'a> {
|
||||||
///
|
///
|
||||||
/// In the replaced case, `size` is never `Auto`.
|
/// In the replaced case, `size` is never `Auto`.
|
||||||
fn solve(&self, get_content_size: Option<impl FnOnce() -> ContentSizes>) -> AxisResult {
|
fn solve(&self, get_content_size: Option<impl FnOnce() -> ContentSizes>) -> AxisResult {
|
||||||
// The provided `get_content_size` is a FnOnce but we may need its result multiple times.
|
|
||||||
// A LazyCell will only invoke it once if needed, and then reuse the result.
|
|
||||||
let content_size = get_content_size.map(LazyCell::new);
|
|
||||||
let solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint {
|
let solve_size = |initial_behavior, stretch_size: Au| -> SizeConstraint {
|
||||||
let stretch_size = stretch_size.max(Au::zero());
|
let stretch_size = stretch_size.max(Au::zero());
|
||||||
if let Some(ref content_size) = content_size {
|
if let Some(get_content_size) = get_content_size {
|
||||||
let preferred_size = Some(self.computed_size.resolve(
|
SizeConstraint::Definite(self.computed_sizes.resolve(
|
||||||
initial_behavior,
|
initial_behavior,
|
||||||
|
Au::zero(),
|
||||||
stretch_size,
|
stretch_size,
|
||||||
content_size,
|
get_content_size,
|
||||||
));
|
))
|
||||||
let min_size = self
|
|
||||||
.computed_min_size
|
|
||||||
.resolve_non_initial(stretch_size, content_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_size = self
|
|
||||||
.computed_max_size
|
|
||||||
.resolve_non_initial(stretch_size, content_size);
|
|
||||||
SizeConstraint::new(preferred_size, min_size, max_size)
|
|
||||||
} else {
|
} else {
|
||||||
let preferred_size = if self.computed_size.is_initial() {
|
self.computed_sizes.resolve_extrinsic(
|
||||||
initial_behavior
|
initial_behavior,
|
||||||
} else {
|
Au::zero(),
|
||||||
self.computed_size
|
Some(stretch_size),
|
||||||
}
|
)
|
||||||
.maybe_resolve_extrinsic(Some(stretch_size));
|
|
||||||
let min_size = self
|
|
||||||
.computed_min_size
|
|
||||||
.maybe_resolve_extrinsic(Some(stretch_size))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_size = self
|
|
||||||
.computed_max_size
|
|
||||||
.maybe_resolve_extrinsic(Some(stretch_size));
|
|
||||||
SizeConstraint::new(preferred_size, min_size, max_size)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if self.box_offsets.either_auto() {
|
if self.box_offsets.either_auto() {
|
||||||
|
@ -891,9 +865,9 @@ impl<'a> AbsoluteAxisSolver<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn override_size(&mut self, size: Au) {
|
fn override_size(&mut self, size: Au) {
|
||||||
self.computed_size = Size::Numeric(size);
|
self.computed_sizes.preferred = Size::Numeric(size);
|
||||||
self.computed_min_size = Size::default();
|
self.computed_sizes.min = Size::default();
|
||||||
self.computed_max_size = Size::default();
|
self.computed_sizes.max = Size::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn origin_for_margin_box(
|
fn origin_for_margin_box(
|
||||||
|
|
|
@ -30,7 +30,7 @@ use webrender_api::ImageKey;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::dom::NodeExt;
|
use crate::dom::NodeExt;
|
||||||
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
use crate::fragment_tree::{BaseFragmentInfo, Fragment, IFrameFragment, ImageFragment};
|
||||||
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size};
|
use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize, Size, Sizes};
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
||||||
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
use crate::{ConstraintSpace, ContainingBlock, SizeConstraint};
|
||||||
|
@ -439,9 +439,8 @@ impl ReplacedContents {
|
||||||
containing_block,
|
containing_block,
|
||||||
style,
|
style,
|
||||||
self.preferred_aspect_ratio(style, &pbm.padding_border_sums),
|
self.preferred_aspect_ratio(style, &pbm.padding_border_sums),
|
||||||
content_box_sizes_and_pbm.content_box_size,
|
&content_box_sizes_and_pbm.content_box_sizes.block,
|
||||||
content_box_sizes_and_pbm.content_min_box_size,
|
&content_box_sizes_and_pbm.content_box_sizes.inline,
|
||||||
content_box_sizes_and_pbm.content_max_box_size,
|
|
||||||
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
|
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -481,15 +480,13 @@ impl ReplacedContents {
|
||||||
///
|
///
|
||||||
/// <https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers>
|
/// <https://drafts.csswg.org/css-sizing-4/#aspect-ratio-size-transfers>
|
||||||
/// <https://github.com/w3c/csswg-drafts/issues/6071#issuecomment-2243986313>
|
/// <https://github.com/w3c/csswg-drafts/issues/6071#issuecomment-2243986313>
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub(crate) fn used_size_as_if_inline_element_from_content_box_sizes(
|
pub(crate) fn used_size_as_if_inline_element_from_content_box_sizes(
|
||||||
&self,
|
&self,
|
||||||
containing_block: &ContainingBlock,
|
containing_block: &ContainingBlock,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
preferred_aspect_ratio: Option<AspectRatio>,
|
preferred_aspect_ratio: Option<AspectRatio>,
|
||||||
box_size: LogicalVec2<Size<Au>>,
|
block_sizes: &Sizes,
|
||||||
min_box_size: LogicalVec2<Size<Au>>,
|
inline_sizes: &Sizes,
|
||||||
max_box_size: LogicalVec2<Size<Au>>,
|
|
||||||
pbm_sums: LogicalVec2<Au>,
|
pbm_sums: LogicalVec2<Au>,
|
||||||
) -> LogicalVec2<Au> {
|
) -> LogicalVec2<Au> {
|
||||||
// <https://drafts.csswg.org/css-images-3/#natural-dimensions>
|
// <https://drafts.csswg.org/css-images-3/#natural-dimensions>
|
||||||
|
@ -520,19 +517,9 @@ impl ReplacedContents {
|
||||||
// First, compute the inline size. Intrinsic values depend on the block sizing properties
|
// First, compute the inline size. Intrinsic values depend on the block sizing properties
|
||||||
// through the aspect ratio, but these can also be intrinsic and depend on the inline size.
|
// through the aspect ratio, but these can also be intrinsic and depend on the inline size.
|
||||||
// Therefore, we tentatively treat intrinsic block sizing properties as their initial value.
|
// Therefore, we tentatively treat intrinsic block sizing properties as their initial value.
|
||||||
let inline_content_size = LazyCell::new(|| {
|
let get_inline_content_size = || {
|
||||||
let get_block_size = || {
|
let get_block_size =
|
||||||
SizeConstraint::new(
|
|| block_sizes.resolve_extrinsic(Size::FitContent, Au::zero(), block_stretch_size);
|
||||||
box_size.block.maybe_resolve_extrinsic(block_stretch_size),
|
|
||||||
min_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(block_stretch_size)
|
|
||||||
.unwrap_or_default(),
|
|
||||||
max_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(block_stretch_size),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
self.content_size(
|
self.content_size(
|
||||||
Direction::Inline,
|
Direction::Inline,
|
||||||
preferred_aspect_ratio,
|
preferred_aspect_ratio,
|
||||||
|
@ -540,24 +527,19 @@ impl ReplacedContents {
|
||||||
&get_inline_fallback_size,
|
&get_inline_fallback_size,
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
});
|
};
|
||||||
let preferred_inline =
|
let (preferred_inline, min_inline, max_inline) = inline_sizes.resolve_each(
|
||||||
box_size
|
Size::FitContent,
|
||||||
.inline
|
Au::zero(),
|
||||||
.resolve(Size::FitContent, inline_stretch_size, &inline_content_size);
|
inline_stretch_size,
|
||||||
let min_inline = min_box_size
|
get_inline_content_size,
|
||||||
.inline
|
);
|
||||||
.resolve_non_initial(inline_stretch_size, &inline_content_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_inline = max_box_size
|
|
||||||
.inline
|
|
||||||
.resolve_non_initial(inline_stretch_size, &inline_content_size);
|
|
||||||
let inline_size = preferred_inline.clamp_between_extremums(min_inline, max_inline);
|
let inline_size = preferred_inline.clamp_between_extremums(min_inline, max_inline);
|
||||||
|
|
||||||
// Now we can compute the block size, using the inline size from above.
|
// Now we can compute the block size, using the inline size from above.
|
||||||
let block_content_size = LazyCell::new(|| -> ContentSizes {
|
let block_content_size = LazyCell::new(|| -> ContentSizes {
|
||||||
let get_inline_size = || {
|
let get_inline_size = || {
|
||||||
if box_size.inline.is_initial() {
|
if inline_sizes.preferred.is_initial() {
|
||||||
// TODO: do we really need to special-case `auto`?
|
// TODO: do we really need to special-case `auto`?
|
||||||
// https://github.com/w3c/csswg-drafts/issues/11236
|
// https://github.com/w3c/csswg-drafts/issues/11236
|
||||||
SizeConstraint::MinMax(min_inline, max_inline)
|
SizeConstraint::MinMax(min_inline, max_inline)
|
||||||
|
@ -573,20 +555,12 @@ impl ReplacedContents {
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
let block_stretch_size =
|
let block_size = block_sizes.resolve(
|
||||||
block_stretch_size.unwrap_or_else(|| block_content_size.max_content);
|
Size::FitContent,
|
||||||
let preferred_block =
|
Au::zero(),
|
||||||
box_size
|
block_stretch_size.unwrap_or_else(|| block_content_size.max_content),
|
||||||
.block
|
|| *block_content_size,
|
||||||
.resolve(Size::FitContent, block_stretch_size, &block_content_size);
|
);
|
||||||
let min_block = min_box_size
|
|
||||||
.block
|
|
||||||
.resolve_non_initial(block_stretch_size, &block_content_size)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let max_block = max_box_size
|
|
||||||
.block
|
|
||||||
.resolve_non_initial(block_stretch_size, &block_content_size);
|
|
||||||
let block_size = preferred_block.clamp_between_extremums(min_block, max_block);
|
|
||||||
|
|
||||||
LogicalVec2 {
|
LogicalVec2 {
|
||||||
inline: inline_size,
|
inline: inline_size,
|
||||||
|
|
|
@ -15,7 +15,7 @@ use style::Zero;
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::geom::Size;
|
use crate::geom::Size;
|
||||||
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
||||||
use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2, SizeConstraint};
|
use crate::{ConstraintSpace, IndefiniteContainingBlock, LogicalVec2};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
pub(crate) enum IntrinsicSizingMode {
|
pub(crate) enum IntrinsicSizingMode {
|
||||||
|
@ -118,9 +118,7 @@ pub(crate) fn outer_inline(
|
||||||
get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult,
|
get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult,
|
||||||
) -> InlineContentSizesResult {
|
) -> InlineContentSizesResult {
|
||||||
let ContentBoxSizesAndPBM {
|
let ContentBoxSizesAndPBM {
|
||||||
content_box_size,
|
content_box_sizes,
|
||||||
content_min_box_size,
|
|
||||||
content_max_box_size,
|
|
||||||
pbm,
|
pbm,
|
||||||
mut depends_on_block_constraints,
|
mut depends_on_block_constraints,
|
||||||
} = style.content_box_sizes_and_padding_border_margin(containing_block);
|
} = style.content_box_sizes_and_padding_border_margin(containing_block);
|
||||||
|
@ -135,25 +133,20 @@ pub(crate) fn outer_inline(
|
||||||
.block
|
.block
|
||||||
.non_auto()
|
.non_auto()
|
||||||
.map(|v| Au::zero().max(v - pbm_sums.block));
|
.map(|v| Au::zero().max(v - pbm_sums.block));
|
||||||
let preferred_block_size = if content_box_size.block.is_initial() &&
|
let automatic_size = if content_box_sizes.block.preferred.is_initial() &&
|
||||||
auto_block_size_stretches_to_containing_block
|
auto_block_size_stretches_to_containing_block
|
||||||
{
|
{
|
||||||
depends_on_block_constraints = true;
|
depends_on_block_constraints = true;
|
||||||
available_block_size
|
Size::Stretch
|
||||||
} else {
|
} else {
|
||||||
content_box_size
|
Size::FitContent
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size)
|
|
||||||
};
|
};
|
||||||
let min_block_size = content_min_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size)
|
|
||||||
.unwrap_or(auto_minimum.block);
|
|
||||||
let max_block_size = content_max_box_size
|
|
||||||
.block
|
|
||||||
.maybe_resolve_extrinsic(available_block_size);
|
|
||||||
get_content_size(&ConstraintSpace::new(
|
get_content_size(&ConstraintSpace::new(
|
||||||
SizeConstraint::new(preferred_block_size, min_block_size, max_block_size),
|
content_box_sizes.block.resolve_extrinsic(
|
||||||
|
automatic_size,
|
||||||
|
auto_minimum.block,
|
||||||
|
available_block_size,
|
||||||
|
),
|
||||||
style.writing_mode,
|
style.writing_mode,
|
||||||
get_preferred_aspect_ratio(&pbm.padding_border_sums),
|
get_preferred_aspect_ratio(&pbm.padding_border_sums),
|
||||||
))
|
))
|
||||||
|
@ -180,14 +173,14 @@ pub(crate) fn outer_inline(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let (preferred_min_content, preferred_max_content, preferred_depends_on_block_constraints) =
|
let (preferred_min_content, preferred_max_content, preferred_depends_on_block_constraints) =
|
||||||
resolve_non_initial(content_box_size.inline)
|
resolve_non_initial(content_box_sizes.inline.preferred)
|
||||||
.unwrap_or_else(|| resolve_non_initial(Size::FitContent).unwrap());
|
.unwrap_or_else(|| resolve_non_initial(Size::FitContent).unwrap());
|
||||||
let (min_min_content, min_max_content, min_depends_on_block_constraints) = resolve_non_initial(
|
let (min_min_content, min_max_content, min_depends_on_block_constraints) = resolve_non_initial(
|
||||||
content_min_box_size.inline,
|
content_box_sizes.inline.min,
|
||||||
)
|
)
|
||||||
.unwrap_or((auto_minimum.inline, auto_minimum.inline, false));
|
.unwrap_or((auto_minimum.inline, auto_minimum.inline, false));
|
||||||
let (max_min_content, max_max_content, max_depends_on_block_constraints) =
|
let (max_min_content, max_max_content, max_depends_on_block_constraints) =
|
||||||
resolve_non_initial(content_max_box_size.inline)
|
resolve_non_initial(content_box_sizes.inline.max)
|
||||||
.map(|(min_content, max_content, depends_on_block_constraints)| {
|
.map(|(min_content, max_content, depends_on_block_constraints)| {
|
||||||
(
|
(
|
||||||
Some(min_content),
|
Some(min_content),
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::dom_traversal::Contents;
|
||||||
use crate::fragment_tree::FragmentFlags;
|
use crate::fragment_tree::FragmentFlags;
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
AuOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides, PhysicalSize,
|
AuOrAuto, LengthPercentageOrAuto, LogicalSides, LogicalVec2, PhysicalSides, PhysicalSize,
|
||||||
PhysicalVec, Size,
|
PhysicalVec, Size, Sizes,
|
||||||
};
|
};
|
||||||
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
use crate::{ContainingBlock, IndefiniteContainingBlock};
|
||||||
|
|
||||||
|
@ -189,9 +189,7 @@ impl AspectRatio {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct ContentBoxSizesAndPBM {
|
pub(crate) struct ContentBoxSizesAndPBM {
|
||||||
pub content_box_size: LogicalVec2<Size<Au>>,
|
pub content_box_sizes: LogicalVec2<Sizes>,
|
||||||
pub content_min_box_size: LogicalVec2<Size<Au>>,
|
|
||||||
pub content_max_box_size: LogicalVec2<Size<Au>>,
|
|
||||||
pub pbm: PaddingBorderMargin,
|
pub pbm: PaddingBorderMargin,
|
||||||
pub depends_on_block_constraints: bool,
|
pub depends_on_block_constraints: bool,
|
||||||
}
|
}
|
||||||
|
@ -199,9 +197,11 @@ pub(crate) struct ContentBoxSizesAndPBM {
|
||||||
impl From<ContentBoxSizesAndPBM> for ContentBoxSizesAndPBMDeprecated {
|
impl From<ContentBoxSizesAndPBM> for ContentBoxSizesAndPBMDeprecated {
|
||||||
fn from(sizes: ContentBoxSizesAndPBM) -> Self {
|
fn from(sizes: ContentBoxSizesAndPBM) -> Self {
|
||||||
Self {
|
Self {
|
||||||
content_box_size: sizes.content_box_size.map(Size::to_auto_or),
|
content_box_size: sizes
|
||||||
content_min_box_size: sizes.content_min_box_size.map(Size::to_auto_or),
|
.content_box_sizes
|
||||||
content_max_box_size: sizes.content_max_box_size.map(Size::to_numeric),
|
.map(|size| size.preferred.to_auto_or()),
|
||||||
|
content_min_box_size: sizes.content_box_sizes.map(|size| size.min.to_auto_or()),
|
||||||
|
content_max_box_size: sizes.content_box_sizes.map(|size| size.max.to_numeric()),
|
||||||
pbm: sizes.pbm.clone(),
|
pbm: sizes.pbm.clone(),
|
||||||
depends_on_block_constraints: sizes.depends_on_block_constraints,
|
depends_on_block_constraints: sizes.depends_on_block_constraints,
|
||||||
}
|
}
|
||||||
|
@ -560,9 +560,18 @@ impl ComputedValuesExt for ComputedValues {
|
||||||
.content_max_box_size_for_max_size(max_size, &pbm)
|
.content_max_box_size_for_max_size(max_size, &pbm)
|
||||||
.map(|v| v.map(Au::from));
|
.map(|v| v.map(Au::from));
|
||||||
ContentBoxSizesAndPBM {
|
ContentBoxSizesAndPBM {
|
||||||
content_box_size,
|
content_box_sizes: LogicalVec2 {
|
||||||
content_min_box_size,
|
block: Sizes::new(
|
||||||
content_max_box_size,
|
content_box_size.block,
|
||||||
|
content_min_box_size.block,
|
||||||
|
content_max_box_size.block,
|
||||||
|
),
|
||||||
|
inline: Sizes::new(
|
||||||
|
content_box_size.inline,
|
||||||
|
content_min_box_size.inline,
|
||||||
|
content_max_box_size.inline,
|
||||||
|
),
|
||||||
|
},
|
||||||
pbm,
|
pbm,
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::formatting_contexts::{
|
||||||
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
|
use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment};
|
||||||
use crate::geom::{
|
use crate::geom::{
|
||||||
LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size,
|
LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size,
|
||||||
SizeConstraint,
|
SizeConstraint, Sizes,
|
||||||
};
|
};
|
||||||
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength};
|
||||||
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult};
|
||||||
|
@ -155,18 +155,16 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> {
|
||||||
style,
|
style,
|
||||||
independent_context
|
independent_context
|
||||||
.preferred_aspect_ratio(&pbm.padding_border_sums),
|
.preferred_aspect_ratio(&pbm.padding_border_sums),
|
||||||
LogicalVec2 {
|
&Sizes::new(
|
||||||
inline: option_f32_to_size(content_box_known_dimensions.width),
|
option_f32_to_size(content_box_known_dimensions.height),
|
||||||
block: option_f32_to_size(content_box_known_dimensions.height),
|
Size::Initial,
|
||||||
},
|
Size::Initial,
|
||||||
LogicalVec2 {
|
),
|
||||||
inline: Size::Numeric(Au::zero()),
|
&Sizes::new(
|
||||||
block: Size::Numeric(Au::zero()),
|
option_f32_to_size(content_box_known_dimensions.width),
|
||||||
},
|
Size::Initial,
|
||||||
LogicalVec2 {
|
Size::Initial,
|
||||||
inline: Size::Initial,
|
),
|
||||||
block: Size::Initial,
|
|
||||||
},
|
|
||||||
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
|
pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum(),
|
||||||
)
|
)
|
||||||
.to_physical_size(self.style.writing_mode);
|
.to_physical_size(self.style.writing_mode);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue