mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
layout: Fix intrinsic contributions of anonymous blocks (#34719)
In order to compute the inline min-content and max-content contributions of an anonymous block, we were finding its min-content and max-content inline size with a SizeConstraint coming from the block size of the box. However, anonymous blocks do not establish a containing block for their contents, so this patch uses a SizeConstraint from the block size of the containing block. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
1157fa28b3
commit
09408ae10b
6 changed files with 91 additions and 22 deletions
|
@ -410,8 +410,9 @@ fn compute_inline_content_sizes_for_block_level_boxes(
|
||||||
&base.style,
|
&base.style,
|
||||||
containing_block,
|
containing_block,
|
||||||
&LogicalVec2::zero(),
|
&LogicalVec2::zero(),
|
||||||
false, /* auto_block_size_stretches_to_containing_block */
|
false, /* auto_block_size_stretches_to_containing_block */
|
||||||
false, /* is_table */
|
false, /* is_table */
|
||||||
|
!matches!(base.style.pseudo(), Some(PseudoElement::ServoAnonymousBox)),
|
||||||
|_| None, /* TODO: support preferred aspect ratios on non-replaced boxes */
|
|_| None, /* TODO: support preferred aspect ratios on non-replaced boxes */
|
||||||
|constraint_space| {
|
|constraint_space| {
|
||||||
base.inline_content_sizes(layout_context, constraint_space, contents)
|
base.inline_content_sizes(layout_context, constraint_space, contents)
|
||||||
|
|
|
@ -216,6 +216,7 @@ impl IndependentFormattingContext {
|
||||||
auto_minimum,
|
auto_minimum,
|
||||||
auto_block_size_stretches_to_containing_block,
|
auto_block_size_stretches_to_containing_block,
|
||||||
is_table,
|
is_table,
|
||||||
|
true, /* establishes_containing_block */
|
||||||
|padding_border_sums| self.preferred_aspect_ratio(padding_border_sums),
|
|padding_border_sums| self.preferred_aspect_ratio(padding_border_sums),
|
||||||
|constraint_space| self.inline_content_sizes(layout_context, constraint_space),
|
|constraint_space| self.inline_content_sizes(layout_context, constraint_space),
|
||||||
)
|
)
|
||||||
|
|
|
@ -871,6 +871,14 @@ impl SizeConstraint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<AuOrAuto> for SizeConstraint {
|
||||||
|
fn from(size: AuOrAuto) -> Self {
|
||||||
|
size.non_auto()
|
||||||
|
.map(SizeConstraint::Definite)
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub(crate) struct Sizes {
|
pub(crate) struct Sizes {
|
||||||
/// <https://drafts.csswg.org/css-sizing-3/#preferred-size-properties>
|
/// <https://drafts.csswg.org/css-sizing-3/#preferred-size-properties>
|
||||||
|
|
|
@ -109,12 +109,14 @@ impl From<Au> for ContentSizes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn outer_inline(
|
pub(crate) fn outer_inline(
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
containing_block: &IndefiniteContainingBlock,
|
containing_block: &IndefiniteContainingBlock,
|
||||||
auto_minimum: &LogicalVec2<Au>,
|
auto_minimum: &LogicalVec2<Au>,
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
is_table: bool,
|
is_table: bool,
|
||||||
|
establishes_containing_block: bool,
|
||||||
get_preferred_aspect_ratio: impl FnOnce(&LogicalVec2<Au>) -> Option<AspectRatio>,
|
get_preferred_aspect_ratio: impl FnOnce(&LogicalVec2<Au>) -> Option<AspectRatio>,
|
||||||
get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult,
|
get_content_size: impl FnOnce(&ConstraintSpace) -> InlineContentSizesResult,
|
||||||
) -> InlineContentSizesResult {
|
) -> InlineContentSizesResult {
|
||||||
|
@ -129,28 +131,40 @@ pub(crate) fn outer_inline(
|
||||||
inline: pbm.padding_border_sums.inline + margin.inline_sum(),
|
inline: pbm.padding_border_sums.inline + margin.inline_sum(),
|
||||||
};
|
};
|
||||||
let content_size = LazyCell::new(|| {
|
let content_size = LazyCell::new(|| {
|
||||||
let available_block_size = containing_block
|
let constraint_space = if establishes_containing_block {
|
||||||
.size
|
let available_block_size = containing_block
|
||||||
.block
|
.size
|
||||||
.non_auto()
|
.block
|
||||||
.map(|v| Au::zero().max(v - pbm_sums.block));
|
.non_auto()
|
||||||
let automatic_size = if content_box_sizes.block.preferred.is_initial() &&
|
.map(|v| Au::zero().max(v - pbm_sums.block));
|
||||||
auto_block_size_stretches_to_containing_block
|
let automatic_size = if content_box_sizes.block.preferred.is_initial() &&
|
||||||
{
|
auto_block_size_stretches_to_containing_block
|
||||||
depends_on_block_constraints = true;
|
{
|
||||||
Size::Stretch
|
depends_on_block_constraints = true;
|
||||||
|
Size::Stretch
|
||||||
|
} else {
|
||||||
|
Size::FitContent
|
||||||
|
};
|
||||||
|
ConstraintSpace::new(
|
||||||
|
content_box_sizes.block.resolve_extrinsic(
|
||||||
|
automatic_size,
|
||||||
|
auto_minimum.block,
|
||||||
|
available_block_size,
|
||||||
|
),
|
||||||
|
style.writing_mode,
|
||||||
|
get_preferred_aspect_ratio(&pbm.padding_border_sums),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Size::FitContent
|
// This assumes that there is no preferred aspect ratio, or that there is no
|
||||||
|
// block size constraint to be transferred so the ratio is irrelevant.
|
||||||
|
// We only get into here for anonymous blocks, for which the assumption holds.
|
||||||
|
ConstraintSpace::new(
|
||||||
|
containing_block.size.block.into(),
|
||||||
|
containing_block.writing_mode,
|
||||||
|
None,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
get_content_size(&ConstraintSpace::new(
|
get_content_size(&constraint_space)
|
||||||
content_box_sizes.block.resolve_extrinsic(
|
|
||||||
automatic_size,
|
|
||||||
auto_minimum.block,
|
|
||||||
available_block_size,
|
|
||||||
),
|
|
||||||
style.writing_mode,
|
|
||||||
get_preferred_aspect_ratio(&pbm.padding_border_sums),
|
|
||||||
))
|
|
||||||
});
|
});
|
||||||
let resolve_non_initial = |inline_size| {
|
let resolve_non_initial = |inline_size| {
|
||||||
Some(match inline_size {
|
Some(match inline_size {
|
||||||
|
|
13
tests/wpt/meta/MANIFEST.json
vendored
13
tests/wpt/meta/MANIFEST.json
vendored
|
@ -81587,6 +81587,19 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"intrinsic-size-with-anonymous-block.html": [
|
||||||
|
"5ddcefbbe1d8e133a80a06e6fb6c3115e886bd89",
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/css/CSS2/reference/ref-filled-green-100px-square.xht",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"intrinsic-size-with-negative-margins.html": [
|
"intrinsic-size-with-negative-margins.html": [
|
||||||
"93dfc3dfd770be960eec71bc00082a04e7385e97",
|
"93dfc3dfd770be960eec71bc00082a04e7385e97",
|
||||||
[
|
[
|
||||||
|
|
32
tests/wpt/tests/css/CSS2/normal-flow/intrinsic-size-with-anonymous-block.html
vendored
Normal file
32
tests/wpt/tests/css/CSS2/normal-flow/intrinsic-size-with-anonymous-block.html
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Intrinsic size of an atomic inline with an anonymous block</title>
|
||||||
|
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#inlineblock-width">
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#inline-replaced-width">
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level">
|
||||||
|
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="
|
||||||
|
#test contains both inline-level contents (the canvas) and block-level (the <p>).
|
||||||
|
Then the canvas is wrapped inside an anonymous block, but it still resolves its percentage against #test.
|
||||||
|
So the canvas is 100px tall, and thus 100px wide because of its aspect ratio.
|
||||||
|
Therefore #test is 100px wide too.
|
||||||
|
">
|
||||||
|
<style>
|
||||||
|
#test {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100px;
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
#test > canvas {
|
||||||
|
height: 100%;
|
||||||
|
background: red;
|
||||||
|
position: relative;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div id="test">
|
||||||
|
<canvas width="10" height="10"></canvas>
|
||||||
|
<p></p>
|
||||||
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue