Bug 1467209 - Implement contain:size for flexContainerFrame, add reftests.
MozReview-Commit-ID: AaVJATn1Gxf
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -3990,16 +3990,22 @@ ResolveFlexContainerMainSize(const Reflo
nscoord largestLineOuterSize = GetLargestLineMainSize(aFirstLine);
if (largestLineOuterSize <= aAvailableBSizeForContent) {
return aAvailableBSizeForContent;
}
return std::min(aTentativeMainSize, largestLineOuterSize);
}
+ // Column-oriented case, with size-containment:
+ // Behave as if we had no content and just use our MinBSize.
+ if (aReflowInput.mStyleDisplay->IsContainSize()) {
+ return aReflowInput.ComputedMinBSize();
+ }
+
// Column-oriented case, with auto BSize:
// Resolve auto BSize to the largest FlexLine length, clamped to our
// computed min/max main-size properties.
// XXXdholbert Handle constrained-aAvailableBSizeForContent case here.
nscoord largestLineOuterSize = GetLargestLineMainSize(aFirstLine);
return NS_CSS_MINMAX(largestLineOuterSize,
aReflowInput.ComputedMinBSize(),
aReflowInput.ComputedMaxBSize());
@@ -4048,16 +4054,22 @@ nsFlexContainerFrame::ComputeCrossSize(c
// our children" is just the sum of our FlexLines' BSizes (cross sizes).
aStatus.SetIncomplete();
if (aSumLineCrossSizes <= aAvailableBSizeForContent) {
return aAvailableBSizeForContent;
}
return std::min(effectiveComputedBSize, aSumLineCrossSizes);
}
+ // Row-oriented case, with size-containment:
+ // Behave as if we had no content and just use our MinBSize.
+ if (aReflowInput.mStyleDisplay->IsContainSize()) {
+ return aReflowInput.ComputedMinBSize();
+ }
+
// Row-oriented case (cross axis is block axis), with auto BSize:
// Shrink-wrap our line(s), subject to our min-size / max-size
// constraints in that (block) axis.
// XXXdholbert Handle constrained-aAvailableBSizeForContent case here.
*aIsDefinite = false;
return NS_CSS_MINMAX(aSumLineCrossSizes,
aReflowInput.ComputedMinBSize(),
aReflowInput.ComputedMaxBSize());
@@ -4873,23 +4885,25 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
// starting w/ content-box size & growing from there:
LogicalSize desiredSizeInFlexWM =
aAxisTracker.LogicalSizeFromFlexRelativeSizes(aContentBoxMainSize,
contentBoxCrossSize);
// Add border/padding (w/ skipSides already applied):
desiredSizeInFlexWM.ISize(flexWM) += containerBP.IStartEnd(flexWM);
desiredSizeInFlexWM.BSize(flexWM) += containerBP.BStartEnd(flexWM);
- if (flexContainerAscent == nscoord_MIN) {
+ if (flexContainerAscent == nscoord_MIN || aReflowInput.mStyleDisplay->IsContainSize()) {
// Still don't have our baseline set -- this happens if we have no
// children (or if our children are huge enough that they have nscoord_MIN
// as their baseline... in which case, we'll use the wrong baseline, but no
// big deal)
+ // this should also happen if we want to pretend we have no
+ // children (e.g. contain:size)
NS_WARNING_ASSERTION(
- lines.getFirst()->IsEmpty(),
+ lines.getFirst()->IsEmpty() || aReflowInput.mStyleDisplay->IsContainSize(),
"Have flex items but didn't get an ascent - that's odd (or there are "
"just gigantic sizes involved)");
// Per spec, synthesize baseline from the flex container's content box
// (i.e. use block-end side of content-box)
// XXXdholbert This only makes sense if parent's writing mode is
// horizontal (& even then, really we should be using the BSize in terms
// of the parent's writing mode, not ours). Clean up in bug 1155322.
flexContainerAscent = desiredSizeInFlexWM.BSize(flexWM);
@@ -5176,26 +5190,28 @@ nsFlexContainerFrame::IntrinsicISize(gfx
return containerISize;
}
/* virtual */ nscoord
nsFlexContainerFrame::GetMinISize(gfxContext* aRenderingContext)
{
DISPLAY_MIN_WIDTH(this, mCachedMinISize);
if (mCachedMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
- mCachedMinISize = IntrinsicISize(aRenderingContext,
- nsLayoutUtils::MIN_ISIZE);
+ mCachedMinISize = StyleDisplay()->IsContainSize()
+ ? 0
+ : IntrinsicISize(aRenderingContext, nsLayoutUtils::MIN_ISIZE);
}
return mCachedMinISize;
}
/* virtual */ nscoord
nsFlexContainerFrame::GetPrefISize(gfxContext* aRenderingContext)
{
DISPLAY_PREF_WIDTH(this, mCachedPrefISize);
if (mCachedPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
- mCachedPrefISize = IntrinsicISize(aRenderingContext,
- nsLayoutUtils::PREF_ISIZE);
+ mCachedPrefISize = StyleDisplay()->IsContainSize()
+ ? 0
+ : IntrinsicISize(aRenderingContext, nsLayoutUtils::PREF_ISIZE);
}
return mCachedPrefISize;
}
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-flex-001-ref.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>CSS Reftest Reference</title>
+ <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+ <style>
+ div {
+ display: flex;
+ border: 1em solid green;
+ }
+ .height-ref {
+ height: 50px;
+ background: lightblue;
+ }
+ .width-ref {
+ width: 50px;
+ }
+ .floatLBasic-ref {
+ float: left;
+ width: 0;
+ }
+ .floatLWidth-ref {
+ float: left;
+ width: 50px;
+ }
+ </style>
+</head>
+<body>
+ <div></div>
+ <br>
+
+ <div class="height-ref"></div>
+ <br>
+
+ <div class="height-ref"></div>
+ <br>
+
+ <div class="width-ref"></div>
+ <br>
+
+ <div class="width-ref"></div>
+ <br>
+
+ <div class="floatLBasic-ref"></div>
+ <br>
+
+ <div class="floatLWidth-ref"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-flex-001.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: 'contain: size' on flex elements should zero the height and/or width if unspecified, and should ensure baseline alignment consistency with empty (0x0) objects of the same type.</title>
+ <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+ <link rel="match" href="contain-size-flex-001-ref.html">
+ <style>
+ div {
+ display: flex;
+ contain:size;
+ border: 1em solid green;
+ background: red;
+ color: transparent;
+ }
+ .minHeight {
+ min-height: 50px;
+ background: lightblue;
+ }
+ .height {
+ height: 50px;
+ background: lightblue;
+ }
+ .maxWidth {
+ max-width: 50px;
+ }
+ .width {
+ width: 50px;
+ }
+ .floatLBasic {
+ float: left;
+ width: auto;
+ }
+ .floatLWidth {
+ float: left;
+ width: 50px;
+ }
+ </style>
+</head>
+<body>
+ <div>CSS Test: A size-contained flex element with no specified size should render at 0 height regardless of content.</div>
+ <br>
+
+ <div class="minHeight">CSS Test: A size-contained flex element with specified min-height should render at given min-height regardless of content.</div>
+ <br>
+
+ <div class="height">CSS Test: A size-contained flex element with specified height should render at given height regardless of content.</div>
+ <br>
+
+ <div class="maxWidth">CSS Test: A size-contained flex element with specified max-width should render at given max-width and zero height regardless of content.</div>
+ <br>
+
+ <div class="width">CSS Test: A size-contained flex element with specified width should render at given width and zero height regardless of content.</div>
+ <br>
+
+ <div class="floatLBasic">CSS Test: A size-contained floated flex element with auto width and no specified height should render at 0px by 0px regardless of content.</div>
+ <br>
+
+ <div class="floatLWidth">CSS Test: A size-contained floated flex element with specified width and no specified height should render at given width and 0 height regardless of content.</div>
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -10,8 +10,9 @@ pref(layout.css.overflow-clip-box.enable
== contain-paint-containing-block-fixed-001.html contain-paint-containing-block-fixed-001-ref.html
== contain-paint-formatting-context-float-001.html contain-paint-formatting-context-float-001-ref.html
== contain-paint-formatting-context-margin-001.html contain-paint-formatting-context-margin-001-ref.html
== contain-paint-stacking-context-001a.html contain-paint-stacking-context-001-ref.html
== contain-paint-stacking-context-001b.html contain-paint-stacking-context-001-ref.html
== contain-size-button-001.html contain-size-button-001-ref.html
== contain-size-block-001.html contain-size-block-001-ref.html
== contain-size-inline-block-001.html contain-size-inline-block-001-ref.html
+== contain-size-flex-001.html contain-size-flex-001-ref.html