Bug 1467209 - Implement contain:size for flexContainerFrame. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Fri, 29 Jun 2018 10:31:22 -0700
changeset 815211 cb91a1a0f44ebfac3b1314db0ce407b30a112675
parent 815210 0e41f67e74c6aa759cca728bf871147af54fe360
push id115462
push userbmo:mreschenberg@berkeley.edu
push dateFri, 06 Jul 2018 22:06:52 +0000
bugs1467209
milestone63.0a1
Bug 1467209 - Implement contain:size for flexContainerFrame. MozReview-Commit-ID: 46BFbEGa7uz
layout/generic/nsFlexContainerFrame.cpp
layout/reftests/w3c-css/submitted/contain/contain-size-flex-001-ref.html
layout/reftests/w3c-css/submitted/contain/contain-size-flex-001.html
layout/reftests/w3c-css/submitted/contain/contain-size-inline-flex-001-ref.html
layout/reftests/w3c-css/submitted/contain/contain-size-inline-flex-001.html
layout/reftests/w3c-css/submitted/contain/reftest.list
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -4050,16 +4050,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());
@@ -4108,16 +4114,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());
@@ -4610,19 +4622,21 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
 
   GenerateFlexLines(aPresContext, aReflowInput,
                     aContentBoxMainSize,
                     aAvailableBSizeForContent,
                     aStruts, aAxisTracker,
                     aMainGapSize,
                     placeholderKids, lines);
 
-  if (lines.getFirst()->IsEmpty() &&
-      !lines.getFirst()->getNext()) {
-    // We have no flex items, our parent should synthesize a baseline if needed.
+  if ((lines.getFirst()->IsEmpty() && !lines.getFirst()->getNext()) ||
+      aReflowInput.mStyleDisplay->IsContainSize()) {
+    // If have no flex items, or if we  are size contained and
+    // want to behave as if we have none, our parent
+    // should synthesize a baseline if needed.
     AddStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE);
   } else {
     RemoveStateBits(NS_STATE_FLEX_SYNTHESIZE_BASELINE);
   }
 
   // Construct our computed info if we've been asked to do so. This is
   // necessary to do now so we can capture some computed values for
   // FlexItems during layout that would not otherwise be saved (like
@@ -5286,26 +5300,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,49 @@
+<!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>
+  .basic {
+    display: flex;
+    border: 1em solid green;
+  }
+  .height-ref {
+    height: 40px;
+    background: lightblue;
+  }
+  .width-ref {
+    width: 40px;
+  }
+  .floatLBasic-ref {
+    float: left;
+  }
+  .floatLWidth-ref {
+    float: left;
+    width: 40px;
+  }
+  </style>
+</head>
+<body>
+  <div class="basic"></div>
+  <br>
+
+  <div class="basic height-ref"></div>
+  <br>
+
+  <div class="basic height-ref"></div>
+  <br>
+
+  <div class="basic width-ref"></div>
+  <br>
+
+  <div class="basic width-ref"></div>
+  <br>
+
+  <div class="basic floatLBasic-ref"></div>
+  <br>
+
+  <div class="basic 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,72 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: size' on flex elements should cause them to be sized and baseline-aligned as if they had no contents.</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-size">
+  <link rel="match" href="contain-size-flex-001-ref.html">
+  <style>
+  .contain {
+    display: flex;
+    contain:size;
+    border: 1em solid green;
+    background: red;
+  }
+  .innerContents {
+    color: transparent;
+    height: 100px;
+    width: 100px;
+  }
+  .minHeight {
+    min-height: 40px;
+    background: lightblue;
+  }
+  .height {
+    height: 40px;
+    background: lightblue;
+  }
+  .maxWidth {
+    max-width: 40px;
+  }
+  .width {
+    width: 40px;
+  }
+  .floatLBasic {
+    float: left;
+  }
+  .floatLWidth {
+    float: left;
+    width: 40px;
+  }
+  </style>
+</head>
+<body>
+  <!--CSS Test: A size-contained flex element with no specified size should render at 0 height regardless of content.-->
+  <div class="contain"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--CSS Test: A size-contained flex element with specified min-height should render at given min-height regardless of content.-->
+  <div class="contain minHeight"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--CSS Test: A size-contained flex element with specified height should render at given height regardless of content.-->
+  <div class="contain height"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--CSS Test: A size-contained flex element with specified max-width should render at given max-width and zero height regardless of content.-->
+  <div class="contain maxWidth"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--CSS Test: A size-contained flex element with specified width should render at given width and zero height regardless of content.-->
+  <div class="contain width"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--CSS Test: A size-contained floated flex element with no specified size should render at 0px by 0px regardless of content.-->
+  <div class="contain floatLBasic"><div class="innerContents">inner</div></div>
+  <br>
+
+  <!--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 class="contain floatLWidth"><div class="innerContents">inner</div></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-inline-flex-001-ref.html
@@ -0,0 +1,23 @@
+<!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>
+  .basic {
+    border: 1em solid green;
+    display: inline-flex;
+  }
+  .width-ref {
+    width: 50px;
+  }
+  </style>
+</head>
+<body>
+  aa<div class="basic"></div>bb
+  <br>
+
+  aa<div class="basic width-ref"></div>bb
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-inline-flex-001.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: size' on inline-flex elements should cause them to be sized and baseline-aligned as if they had no contents.</title>
+  <link rel="author" title="Morgan Rae Reschenberg" href="mailto:mreschenberg@berkeley.edu">
+  <link rel="help" href="https://drafts.csswg.org/css-contain/#containment-size">
+  <link rel="match" href="contain-size-inline-flex-001-ref.html">
+  <style>
+  .contain {
+    display: inline-flex;
+    contain:size;
+    border: 1em solid green;
+    background: red;
+  }
+  .innerContents {
+    color: transparent;
+    height: 100px;
+    width: 100px;
+  }
+  .width {
+    width: 50px;
+  }
+  </style>
+</head>
+<body>
+  <!--CSS Test: A size-contained inline-flex element without dimensions should ensure baseline alignment behaviour matches that of an empty object of the same type.-->
+  aa<div class="contain"><div class="innerContents">inner</div></div>bb
+  <br>
+
+  <!--CSS Test: A size-contained inline-flex element with specified width should ensure baseline alignment behaviour matches that of an empty object of the same type.-->
+  aa<div class="contain width"><div class="innerContents">inner</div></div>bb
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -15,9 +15,11 @@ pref(layout.css.overflow-clip-box.enable
 == contain-paint-ignored-cases-no-principal-box-001.html contain-paint-ignored-cases-no-principal-box-001-ref.html
 == contain-paint-ignored-cases-ruby-containing-block-001.html contain-paint-ignored-cases-ruby-containing-block-001-ref.html
 == contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html contain-paint-ignored-cases-ruby-stacking-and-clipping-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
+== contain-size-inline-flex-001.html contain-size-inline-flex-001-ref.html
 == contain-size-multicol-001.html contain-size-multicol-001-ref.html