Bug 1672462 - Compute flex item's content size suggestion in inline axis via nsIFrame::ComputeSize. r=emilio

Flex item's content size suggestion is the min-content size in the main
axis. Quoting from the CSS Sizing spec, section "5.1. Intrinsic Sizes",

    The min-content size of a box in each axis is the size it would have
    if it was a float given an auto size in that axis (and no minimum or
    maximum size in that axis) and if its containing block was
    zero-sized in that axis. (In other words, the minimum size it has
    when sized as “shrink-to-fit”.)

However, all the frame types' GetMinISize() doesn't consider aspect
ratio (either the intrinsic aspect ratio on images or svg, or the
preferred aspect ratio set by the aspect-ratio property). That is, we
currently don't allow `aspect ratio * definite block-size` as part of
the equation in `inline-size:min-content` (bug 1646100 or bug 1670151).

Luckily, nsIFrame::ComputeSize() already takes care of this [2]. We just
need to add a flag to let ComputeSize() behave as if the flex item had
an auto inline size. The code should be similar to FloatMarginISize() in
BlockReflowInput.cpp except we are calculate the flex item's content-box
size.

[1] https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes
[2] https://searchfox.org/mozilla-central/rev/dbced93f1c57942501c23d4633d01ce59d9087a1/layout/generic/nsContainerFrame.cpp#2732,2735-2736

Differential Revision: https://phabricator.services.mozilla.com/D94802
This commit is contained in:
Ting-Yu Lin 2020-10-29 22:43:53 +00:00
Родитель 766ede2dec
Коммит c4f22dc89f
9 изменённых файлов: 41 добавлений и 16 удалений

Просмотреть файл

@ -49,10 +49,19 @@ enum class ComputeSizeFlag : uint8_t {
*/
ShrinkWrap,
/**
* Set if we'd like to compute our 'auto' isize, regardless of our actual
* corresponding computed value. (e.g. to get an intrinsic isize for flex
* items when resolving automatic minimum size in the main axis during flexbox
* layout.)
*/
UseAutoISize,
/**
* Set if we'd like to compute our 'auto' bsize, regardless of our actual
* corresponding computed value. (e.g. to get an intrinsic height for flex
* items with "min-height: auto" to use during flexbox layout.)
* corresponding computed value. (e.g. to get an intrinsic bsize for flex
* items when resolving automatic minimum size in the main axis during flexbox
* layout.)
*/
UseAutoBSize,

Просмотреть файл

@ -991,6 +991,7 @@ LogicalSize nsContainerFrame::ComputeAutoSize(
// flex-basis:content.
const nsStylePosition* pos = StylePosition();
if (pos->ISize(aWM).IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize) ||
(pos->mFlexBasis.IsContent() && IsFlexItem() &&
nsFlexContainerFrame::IsItemInlineAxisMainAxis(this))) {
result.ISize(aWM) =
@ -2482,7 +2483,8 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions(
// a * (b / c) because of its reduced accuracy relative to a * b / c
// or (a * b) / c (which are equivalent).
const bool isAutoISize = inlineStyleCoord->IsAuto();
const bool isAutoISize = inlineStyleCoord->IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize);
const bool isAutoBSize =
nsLayoutUtils::IsAutoBSize(*blockStyleCoord, aCBSize.BSize(aWM)) ||
aFlags.contains(ComputeSizeFlag::UseAutoBSize);

Просмотреть файл

@ -1616,8 +1616,21 @@ void nsFlexContainerFrame::ResolveAutoFlexBasisAndMinSize(
if (aFlexItem.IsInlineAxisMainAxis()) {
if (minSizeNeedsToMeasureContent) {
contentSizeSuggestion =
aFlexItem.Frame()->GetMinISize(aItemReflowInput.mRenderingContext);
// Compute the flex item's content size suggestion, which is the
// 'min-content' size on the main axis.
// https://drafts.csswg.org/css-flexbox-1/#content-size-suggestion
const auto cbWM = aAxisTracker.GetWritingMode();
const auto itemWM = aFlexItem.GetWritingMode();
const nscoord availISize = 0; // for min-content size
const auto sizeInItemWM = aFlexItem.Frame()->ComputeSize(
aItemReflowInput.mRenderingContext, itemWM,
aItemReflowInput.mContainingBlockSize, availISize,
aItemReflowInput.ComputedLogicalMargin().Size(itemWM),
aItemReflowInput.ComputedLogicalBorderPadding().Size(itemWM),
{ComputeSizeFlag::UseAutoISize, ComputeSizeFlag::ShrinkWrap});
contentSizeSuggestion = aAxisTracker.MainComponent(
sizeInItemWM.mLogicalSize.ConvertTo(cbWM, itemWM));
}
NS_ASSERTION(!flexBasisNeedsToMeasureContent,
"flex-basis:auto should have been resolved in the "

Просмотреть файл

@ -6149,8 +6149,10 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize(
}
const bool isOrthogonal = aWM.IsOrthogonalTo(alignCB->GetWritingMode());
const bool isAutoISize = inlineStyleCoord->IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize);
// Compute inline-axis size
if (!inlineStyleCoord->IsAuto()) {
if (!isAutoISize) {
result.ISize(aWM) = ComputeISizeValue(
aRenderingContext, aCBSize.ISize(aWM), boxSizingAdjust.ISize(aWM),
boxSizingToMarginEdgeISize, *inlineStyleCoord, aFlags);
@ -6363,7 +6365,8 @@ LogicalSize nsIFrame::ComputeAutoSize(
LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE);
// don't bother setting it if the result won't be used
if (StylePosition()->ISize(aWM).IsAuto()) {
if (StylePosition()->ISize(aWM).IsAuto() ||
aFlags.contains(ComputeSizeFlag::UseAutoISize)) {
nscoord availBased =
aAvailableISize - aMargin.ISize(aWM) - aBorderPadding.ISize(aWM);
result.ISize(aWM) = ShrinkWidthToFit(aRenderingContext, availBased, aFlags);

Просмотреть файл

@ -0,0 +1,4 @@
[flex-aspect-ratio-img-column-011.html]
[.flexbox 5]
expected: FAIL # bogus test
bug: https://github.com/web-platform-tests/wpt/pull/26299

Просмотреть файл

@ -1,3 +0,0 @@
[flex-minimum-width-flex-items-007.xht]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1665532

Просмотреть файл

@ -0,0 +1,3 @@
[flex-minimum-width-flex-items-013.html]
expected: FAIL
bug: https://github.com/web-platform-tests/wpt/pull/26299

Просмотреть файл

@ -1,3 +0,0 @@
[flexbox-min-width-auto-002a.html]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1665532

Просмотреть файл

@ -1,3 +0,0 @@
[flexbox-min-width-auto-002c.html]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1665532