Bug 1467209 - Implement contain:size for flexContianerFrame, add reftests. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Thu, 07 Jun 2018 12:26:35 -0700
changeset 805465 b87961c5c93464c18e6c6a209a3d8a52b99e5894
parent 805464 3144e0bc17969c3a16832d8ea26caf83ed4987e6
push id112669
push userbmo:mreschenberg@berkeley.edu
push dateThu, 07 Jun 2018 21:02:36 +0000
bugs1467209
milestone62.0a1
Bug 1467209 - Implement contain:size for flexContianerFrame, add reftests. MozReview-Commit-ID: AaVJATn1Gxf
layout/generic/nsFlexContainerFrame.cpp
layout/generic/nsFlexContainerFrame.h
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/reftest.list
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -18,16 +18,17 @@
 #include "mozilla/CSSOrderAwareFrameIterator.h"
 #include "mozilla/Logging.h"
 #include <algorithm>
 #include "gfxContext.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/UniquePtr.h"
 #include "WritingModes.h"
+#include "nsLayoutUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::layout;
 
 // Convenience typedefs for helper classes that we forward-declare in .h file
 // (so that nsFlexContainerFrame methods can use them as parameters):
 typedef nsFlexContainerFrame::FlexItem FlexItem;
 typedef nsFlexContainerFrame::FlexLine FlexLine;
@@ -3908,26 +3909,27 @@ GetLargestLineMainSize(const FlexLine* a
  *
  * Guaranteed to return a definite length, i.e. not NS_UNCONSTRAINEDSIZE,
  * aside from cases with huge lengths which happen to compute to that value.
  *
  * (Note: This function should be structurally similar to 'ComputeCrossSize()',
  * except that here, the caller has already grabbed the tentative size from the
  * reflow state.)
  */
-static nscoord
-ResolveFlexContainerMainSize(const ReflowInput& aReflowInput,
+nscoord
+nsFlexContainerFrame::ResolveFlexContainerMainSize(const ReflowInput& aReflowInput,
                              const FlexboxAxisTracker& aAxisTracker,
                              nscoord aTentativeMainSize,
                              nscoord aAvailableBSizeForContent,
                              const FlexLine* aFirstLine,
                              nsReflowStatus& aStatus)
 {
   MOZ_ASSERT(aFirstLine, "null first line pointer");
 
+
   if (aAxisTracker.IsRowOriented()) {
     // Row-oriented --> our main axis is the inline axis, so our main size
     // is our inline size (which should already be resolved).
     return aTentativeMainSize;
   }
 
   if (aTentativeMainSize != NS_INTRINSICSIZE) {
     // Column-oriented case, with fixed BSize:
@@ -3951,16 +3953,20 @@ ResolveFlexContainerMainSize(const Reflo
     nscoord largestLineOuterSize = GetLargestLineMainSize(aFirstLine);
 
     if (largestLineOuterSize <= aAvailableBSizeForContent) {
       return aAvailableBSizeForContent;
     }
     return std::min(aTentativeMainSize, largestLineOuterSize);
   }
 
+  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());
@@ -3971,16 +3977,18 @@ nsFlexContainerFrame::ComputeCrossSize(c
                                        const FlexboxAxisTracker& aAxisTracker,
                                        nscoord aSumLineCrossSizes,
                                        nscoord aAvailableBSizeForContent,
                                        bool* aIsDefinite,
                                        nsReflowStatus& aStatus)
 {
   MOZ_ASSERT(aIsDefinite, "outparam pointer must be non-null");
 
+
+
   if (aAxisTracker.IsColumnOriented()) {
     // Column-oriented --> our cross axis is the inline axis, so our cross size
     // is our inline size (which should already be resolved).
     NS_WARNING_ASSERTION(
       aReflowInput.ComputedISize() != NS_UNCONSTRAINEDSIZE,
       "Unconstrained inline size; this should only result from huge sizes "
       "(not intrinsic sizing w/ orthogonal flows)");
     *aIsDefinite = true;
@@ -4009,16 +4017,20 @@ 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);
   }
 
+  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());
@@ -4834,21 +4846,23 @@ 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(),
       "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
@@ -5136,27 +5150,35 @@ nsFlexContainerFrame::IntrinsicISize(gfx
 
   return containerISize;
 }
 
 /* virtual */ nscoord
 nsFlexContainerFrame::GetMinISize(gfxContext* aRenderingContext)
 {
   DISPLAY_MIN_WIDTH(this, mCachedMinISize);
+  if (this->StyleDisplay()->IsContainSize()) {
+    return 0;
+  }
+
   if (mCachedMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
     mCachedMinISize = IntrinsicISize(aRenderingContext,
                                      nsLayoutUtils::MIN_ISIZE);
   }
 
   return mCachedMinISize;
 }
 
 /* virtual */ nscoord
 nsFlexContainerFrame::GetPrefISize(gfxContext* aRenderingContext)
 {
   DISPLAY_PREF_WIDTH(this, mCachedPrefISize);
+  if (this->StyleDisplay()->IsContainSize()) {
+    return 0;
+  }
+
   if (mCachedPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
     mCachedPrefISize = IntrinsicISize(aRenderingContext,
                                       nsLayoutUtils::PREF_ISIZE);
   }
 
   return mCachedPrefISize;
 }
--- a/layout/generic/nsFlexContainerFrame.h
+++ b/layout/generic/nsFlexContainerFrame.h
@@ -354,16 +354,23 @@ protected:
                          const nsTArray<StrutInfo>& aStruts,
                          const FlexboxAxisTracker& aAxisTracker,
                          nsTArray<nsIFrame*>& aPlaceholders,
                          mozilla::LinkedList<FlexLine>& aLines);
 
   nscoord GetMainSizeFromReflowInput(const ReflowInput& aReflowInput,
                                      const FlexboxAxisTracker& aAxisTracker);
 
+  nscoord ResolveFlexContainerMainSize(const ReflowInput& aReflowInput,
+                                       const FlexboxAxisTracker& aAxisTracker,
+                                       nscoord aTentativeMainSize,
+                                       nscoord aAvailableBSizeForContent,
+                                       const FlexLine* aFirstLine,
+                                       nsReflowStatus& aStatus);
+
   nscoord ComputeCrossSize(const ReflowInput& aReflowInput,
                            const FlexboxAxisTracker& aAxisTracker,
                            nscoord aSumLineCrossSizes,
                            nscoord aAvailableBSizeForContent,
                            bool* aIsDefinite,
                            nsReflowStatus& aStatus);
 
   void SizeItemInCrossAxis(nsPresContext* aPresContext,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-flex-001-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
+  <style>
+  body {
+    margin: 0;
+  }
+  .container {
+    background: red;
+    display:flex;
+    flex-direction: column;
+    border: 8px solid green;
+    height: 0;
+  }
+  </style>
+</head>
+<body>
+  <div class="container">
+  </div>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-flex-001.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: layout' on flexbox with no intrinsic
+    height should cause it to have zero height.</title>
+  <link rel="author" title="Kyle Zentner" href="mailto:zentner.kyle@gmail.com">
+  <link rel="help" href="http://www.w3.org/TR/css-containment-1/#containment-layout">
+  <link rel="match" href="contain-size-flex-001-ref.html">
+  <style>
+  body {
+    margin: 0;
+  }
+  .container {
+    display: flex;
+    flex-direction: column;
+    border: 8px solid green;
+    contain: size;
+  }
+  .inline {
+    display: inline-block;
+    width: 10px;
+    height: 5px;
+  }
+  </style>
+</head>
+<body>
+  <div class="container">
+    <div class="inline"></div>
+    <div class="inline"></div>
+  </div>
+</body>
+</html>
\ No newline at end of file
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -4,13 +4,14 @@ default-preferences pref(layout.css.cont
 == contain-paint-clip-002.html contain-paint-clip-002-ref.html
 == contain-paint-clip-003.html contain-paint-clip-003-ref.html
 == contain-paint-clip-004.html contain-paint-clip-004-ref.html
 == contain-paint-clip-005.html contain-paint-clip-003-ref.html
 == contain-paint-containing-block-absolute-001.html contain-paint-containing-block-absolute-001-ref.html
 == 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-size-flex-001.html contain-size-flex-001-ref.html
 == contain-size-block-001.html contain-size-block-001-ref.html
 == contain-size-block-002.html contain-size-block-002-ref.html
 == contain-size-block-003.html contain-size-block-003-ref.html
 == contain-size-inline-block-001.html contain-size-inline-block-001-ref.html
 == contain-size-inline-block-002.html contain-size-inline-block-002-ref.html
\ No newline at end of file