mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Implement keyword sizes for intrinsic contributions (#33854)
Correctly handle keyword sizes when computing the min-content or max-content contribution of a box. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
831a65917a
commit
faeb31d6c6
5 changed files with 209 additions and 42 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//! <https://drafts.csswg.org/css-sizing/>
|
//! <https://drafts.csswg.org/css-sizing/>
|
||||||
|
|
||||||
|
use std::cell::LazyCell;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -11,7 +12,8 @@ use serde::Serialize;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
|
||||||
use crate::style_ext::{Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated};
|
use crate::geom::Size;
|
||||||
|
use crate::style_ext::{Clamp, ComputedValuesExt, ContentBoxSizesAndPBM};
|
||||||
use crate::{AuOrAuto, IndefiniteContainingBlock, LogicalVec2};
|
use crate::{AuOrAuto, IndefiniteContainingBlock, LogicalVec2};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -120,52 +122,100 @@ pub(crate) fn outer_inline(
|
||||||
auto_block_size_stretches_to_containing_block: bool,
|
auto_block_size_stretches_to_containing_block: bool,
|
||||||
get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> InlineContentSizesResult,
|
get_content_size: impl FnOnce(&IndefiniteContainingBlock) -> InlineContentSizesResult,
|
||||||
) -> InlineContentSizesResult {
|
) -> InlineContentSizesResult {
|
||||||
let ContentBoxSizesAndPBMDeprecated {
|
let ContentBoxSizesAndPBM {
|
||||||
content_box_size,
|
content_box_size,
|
||||||
content_min_box_size,
|
content_min_box_size,
|
||||||
content_max_box_size,
|
content_max_box_size,
|
||||||
pbm,
|
pbm,
|
||||||
mut depends_on_block_constraints,
|
mut depends_on_block_constraints,
|
||||||
} = style
|
} = style.content_box_sizes_and_padding_border_margin(containing_block);
|
||||||
.content_box_sizes_and_padding_border_margin(containing_block)
|
|
||||||
.into();
|
|
||||||
let content_box_min_size = LogicalVec2 {
|
|
||||||
inline: content_min_box_size.inline.auto_is(|| auto_minimum.inline),
|
|
||||||
block: content_min_box_size.block.auto_is(|| auto_minimum.block),
|
|
||||||
};
|
|
||||||
let margin = pbm.margin.map(|v| v.auto_is(Au::zero));
|
let margin = pbm.margin.map(|v| v.auto_is(Au::zero));
|
||||||
let pbm_inline_sum = pbm.padding_border_sums.inline + margin.inline_sum();
|
let pbm_sums = LogicalVec2 {
|
||||||
let adjust = |v: Au| {
|
block: pbm.padding_border_sums.block + margin.block_sum(),
|
||||||
v.clamp_between_extremums(content_box_min_size.inline, content_max_box_size.inline) +
|
inline: pbm.padding_border_sums.inline + margin.inline_sum(),
|
||||||
pbm_inline_sum
|
|
||||||
};
|
};
|
||||||
match content_box_size.inline {
|
let content_size = LazyCell::new(|| {
|
||||||
AuOrAuto::LengthPercentage(inline_size) => InlineContentSizesResult {
|
let available_block_size = containing_block
|
||||||
sizes: adjust(inline_size).into(),
|
.size
|
||||||
depends_on_block_constraints: false,
|
.block
|
||||||
},
|
.non_auto()
|
||||||
AuOrAuto::Auto => {
|
.map(|v| Au::zero().max(v - pbm_sums.block));
|
||||||
let block_size = if content_box_size.block.is_auto() &&
|
let block_size = if content_box_size.block.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;
|
||||||
let outer_block_size = containing_block.size.block;
|
available_block_size
|
||||||
outer_block_size.map(|v| v - pbm.padding_border_sums.block - margin.block_sum())
|
} else {
|
||||||
} else {
|
content_box_size
|
||||||
content_box_size.block
|
.block
|
||||||
}
|
.maybe_resolve_extrinsic(available_block_size)
|
||||||
.map(|v| {
|
}
|
||||||
v.clamp_between_extremums(content_box_min_size.block, content_max_box_size.block)
|
.map(|block_size| {
|
||||||
});
|
let min_block_size = content_min_box_size
|
||||||
let containing_block_for_children =
|
.block
|
||||||
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size);
|
.maybe_resolve_extrinsic(available_block_size)
|
||||||
let content_result = get_content_size(&containing_block_for_children);
|
.unwrap_or(auto_minimum.block);
|
||||||
InlineContentSizesResult {
|
let max_block_size = content_max_box_size
|
||||||
sizes: content_result.sizes.map(adjust),
|
.block
|
||||||
depends_on_block_constraints: content_result.depends_on_block_constraints &&
|
.maybe_resolve_extrinsic(available_block_size);
|
||||||
|
block_size.clamp_between_extremums(min_block_size, max_block_size)
|
||||||
|
})
|
||||||
|
.map_or(AuOrAuto::Auto, AuOrAuto::LengthPercentage);
|
||||||
|
let containing_block_for_children =
|
||||||
|
IndefiniteContainingBlock::new_for_style_and_block_size(style, block_size);
|
||||||
|
get_content_size(&containing_block_for_children)
|
||||||
|
});
|
||||||
|
let resolve_non_initial = |inline_size| {
|
||||||
|
Some(match inline_size {
|
||||||
|
Size::Initial => return None,
|
||||||
|
Size::Numeric(numeric) => (numeric, numeric, false),
|
||||||
|
Size::MinContent => (
|
||||||
|
content_size.sizes.min_content,
|
||||||
|
content_size.sizes.min_content,
|
||||||
|
content_size.depends_on_block_constraints,
|
||||||
|
),
|
||||||
|
Size::MaxContent => (
|
||||||
|
content_size.sizes.max_content,
|
||||||
|
content_size.sizes.max_content,
|
||||||
|
content_size.depends_on_block_constraints,
|
||||||
|
),
|
||||||
|
Size::Stretch | Size::FitContent => (
|
||||||
|
content_size.sizes.min_content,
|
||||||
|
content_size.sizes.max_content,
|
||||||
|
content_size.depends_on_block_constraints,
|
||||||
|
),
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let (preferred_min_content, preferred_max_content, preferred_depends_on_block_constraints) =
|
||||||
|
resolve_non_initial(content_box_size.inline)
|
||||||
|
.unwrap_or_else(|| resolve_non_initial(Size::FitContent).unwrap());
|
||||||
|
let (min_min_content, min_max_content, min_depends_on_block_constraints) = resolve_non_initial(
|
||||||
|
content_min_box_size.inline,
|
||||||
|
)
|
||||||
|
.unwrap_or((auto_minimum.inline, auto_minimum.inline, false));
|
||||||
|
let (max_min_content, max_max_content, max_depends_on_block_constraints) =
|
||||||
|
resolve_non_initial(content_max_box_size.inline)
|
||||||
|
.map(|(min_content, max_content, depends_on_block_constraints)| {
|
||||||
|
(
|
||||||
|
Some(min_content),
|
||||||
|
Some(max_content),
|
||||||
depends_on_block_constraints,
|
depends_on_block_constraints,
|
||||||
}
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
InlineContentSizesResult {
|
||||||
|
sizes: ContentSizes {
|
||||||
|
min_content: preferred_min_content
|
||||||
|
.clamp_between_extremums(min_min_content, max_min_content) +
|
||||||
|
pbm_sums.inline,
|
||||||
|
max_content: preferred_max_content
|
||||||
|
.clamp_between_extremums(min_max_content, max_max_content) +
|
||||||
|
pbm_sums.inline,
|
||||||
},
|
},
|
||||||
|
depends_on_block_constraints: depends_on_block_constraints &&
|
||||||
|
(preferred_depends_on_block_constraints ||
|
||||||
|
min_depends_on_block_constraints ||
|
||||||
|
max_depends_on_block_constraints),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
tests/wpt/meta/MANIFEST.json
vendored
7
tests/wpt/meta/MANIFEST.json
vendored
|
@ -569314,6 +569314,13 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"keyword-sizes-for-intrinsic-contributions.tentative.html": [
|
||||||
|
"5f135d8181b023134eb24e5ec34957e3a25e6765",
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"keyword-sizes-on-floated-element.html": [
|
"keyword-sizes-on-floated-element.html": [
|
||||||
"42ea7ba26d7e1ffd26f8f12bad37e3b18abba0f6",
|
"42ea7ba26d7e1ffd26f8f12bad37e3b18abba0f6",
|
||||||
[
|
[
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[intrinsic-percent-replaced-dynamic-011.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[intrinsic-percent-replaced-dynamic-012.html]
|
|
||||||
expected: FAIL
|
|
114
tests/wpt/tests/css/css-sizing/keyword-sizes-for-intrinsic-contributions.tentative.html
vendored
Normal file
114
tests/wpt/tests/css/css-sizing/keyword-sizes-for-intrinsic-contributions.tentative.html
vendored
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Keyword sizes for intrinsic contributions</title>
|
||||||
|
<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#sizing-values">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#sizing-values">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#intrinsic-contribution">
|
||||||
|
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/10721">
|
||||||
|
<meta assert="The various keyword sizes produce the right min/max-content contributions.">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrapper {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-right: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test {
|
||||||
|
float: left;
|
||||||
|
clear: both;
|
||||||
|
margin: 5px;
|
||||||
|
border: 3px solid;
|
||||||
|
padding: 2px;
|
||||||
|
font: 20px/1 Ahem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the preferred size to small amount, to test that the min size works */
|
||||||
|
.test.min-width > div { width: 0px }
|
||||||
|
.test.min-height > div { height: 0px }
|
||||||
|
|
||||||
|
/* Set the preferred size to big amount, to test that the max size works */
|
||||||
|
.test.max-width > div { width: 200px }
|
||||||
|
.test.max-height > div { height: 200px }
|
||||||
|
|
||||||
|
/* stretch isn't widely supported, fall back to vendor-prefixed alternatives */
|
||||||
|
.width > .stretch { width: -moz-available; width: -webkit-fill-available; width: stretch }
|
||||||
|
.min-width > .stretch { min-width: -moz-available; min-width: -webkit-fill-available; min-width: stretch }
|
||||||
|
.max-width > .stretch { max-width: -moz-available; max-width: -webkit-fill-available; max-width: stretch }
|
||||||
|
.height > .stretch { height: -moz-available; height: -webkit-fill-available; height: stretch }
|
||||||
|
.min-height > .stretch { min-height: -moz-available; min-height: -webkit-fill-available; min-height: stretch }
|
||||||
|
.max-height > .stretch { max-height: -moz-available; max-height: -webkit-fill-available; max-height: stretch }
|
||||||
|
</style>
|
||||||
|
<div id="log"></div>
|
||||||
|
|
||||||
|
<!-- Preferred width -->
|
||||||
|
<div class="wrapper" style="width: 0px">
|
||||||
|
<div class="test width" data-expected-width="70"><div style="width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="70"><div style="width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="70"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="150"><div style="width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 100px">
|
||||||
|
<div class="test width" data-expected-width="70"><div style="width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="90"><div style="width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="90"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="150"><div style="width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 200px">
|
||||||
|
<div class="test width" data-expected-width="70"><div style="width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="150"><div style="width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="150"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test width" data-expected-width="150"><div style="width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Minimum width -->
|
||||||
|
<div class="wrapper" style="width: 0px">
|
||||||
|
<div class="test min-width" data-expected-width="70"><div style="min-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="70"><div style="min-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="70"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="150"><div style="min-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 100px">
|
||||||
|
<div class="test min-width" data-expected-width="70"><div style="min-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="90"><div style="min-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="90"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="150"><div style="min-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 200px">
|
||||||
|
<div class="test min-width" data-expected-width="70"><div style="min-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="150"><div style="min-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="150"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test min-width" data-expected-width="150"><div style="min-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<!-- Maximum width -->
|
||||||
|
<div class="wrapper" style="width: 0px">
|
||||||
|
<div class="test max-width" data-expected-width="70"><div style="max-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="70"><div style="max-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="70"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="150"><div style="max-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 100px">
|
||||||
|
<div class="test max-width" data-expected-width="70"><div style="max-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="90"><div style="max-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="90"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="150"><div style="max-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
<div class="wrapper" style="width: 200px">
|
||||||
|
<div class="test max-width" data-expected-width="70"><div style="max-width: min-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="150"><div style="max-width: fit-content">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="150"><div class="stretch">XXX XXX</div></div>
|
||||||
|
<div class="test max-width" data-expected-width="150"><div style="max-width: max-content">XXX XXX</div></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="/resources/check-layout-th.js"></script>
|
||||||
|
<script>
|
||||||
|
checkLayout(".test");
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue