Bug 1467209 - Implement contain:size for flexContainerFrame, add reftests. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Thu, 07 Jun 2018 12:26:35 -0700
changeset 809302 16783b5defbf700afda318941b73d18bd792a0fc
parent 809301 5024133d58932df1c663a178fb8934fe57fd2222
push id113622
push userbmo:mreschenberg@berkeley.edu
push dateThu, 21 Jun 2018 18:18:48 +0000
bugs1467209
milestone62.0a1
Bug 1467209 - Implement contain:size for flexContainerFrame, add reftests. MozReview-Commit-ID: AaVJATn1Gxf
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/reftest.list
--- 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-orientated 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-orientated 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,21 +4885,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
@@ -5175,27 +5189,29 @@ 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);
+if (mCachedMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
+    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,71 @@
+<!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;
+  }
+  .iFlexBasic-ref {
+    /* This is also hack-y for the same reason as the button tests.
+    Some info about text is leaking causing weird positioning/margins. */
+    vertical-align: top;
+    display: inline-flex;
+    width: 0;
+  }
+  .iFlexWidth-ref {
+    display: inline-flex;
+    width: 50px;
+  }
+  </style>
+</head>
+<body>
+  <div></div>
+  <br>
+
+  outside before<div></div>outside after
+  <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>
+  <br style="clear:both;">
+
+  <div class="iFlexBasic-ref"></div>
+  <br style="clear:both;">
+
+  <div class="iFlexWidth-ref"></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,81 @@
+<!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;
+  }
+  .iFlexBasic {
+    /* This is also hack-y for the same reason as the button tests.
+    Some info about text is leaking causing weird positioning/margins. */
+    vertical-align: top;
+    display: inline-flex;
+    width: auto;
+  }
+  .iFlexWidth {
+    display: inline-flex;
+    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>
+
+  outside before<div>CSS Test: A size-contained flex element should perform baseline alignment as if the container were empty.</div>outside after
+  <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>
+  <br style="clear:both;">
+
+  <div class="iFlexBasic">CSS Test: A size-contained inline-flex element with auto width and no specified height should render at 0px by 0px regardless of content.</div>
+  <br style="clear:both;">
+
+  <div class="iFlexWidth">CSS Test: A size-contained inline-flex element with specified width and no specified height should render at given width and 0 height regardless of content.</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
@@ -7,11 +7,9 @@ default-preferences pref(layout.css.cont
 == contain-paint-clip-005.html contain-paint-clip-003-ref.html
 pref(layout.css.overflow-clip-box.enabled,true) == contain-paint-clip-006.html contain-paint-clip-006-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-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-block-001.html contain-size-block-001-ref.html
-== contain-size-inline-block-001.html contain-size-inline-block-001-ref.html
-== contain-size-button-001.html contain-size-button-001-ref.html
\ No newline at end of file
+== contain-size-flex-001.html contain-size-flex-001-ref.html
\ No newline at end of file