Bug 1467209 - Implement contain:size for blockFrame, add reftests. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Thu, 07 Jun 2018 12:22:15 -0700
changeset 811587 eec53afa1e151dac6f953c3abc9d3eb886a6342e
parent 811586 c41b31626bfda3d8e4cc6ffc00788b1e43fb12f4
child 811588 abc2a05f2f128952da8ae5f24ad8549fc70ed0a7
push id114362
push userbmo:mreschenberg@berkeley.edu
push dateWed, 27 Jun 2018 22:00:04 +0000
bugs1467209
milestone62.0a1
Bug 1467209 - Implement contain:size for blockFrame, add reftests. MozReview-Commit-ID: 9lDZkAllu8I
layout/generic/nsBlockFrame.cpp
layout/reftests/w3c-css/submitted/contain/contain-size-block-001-ref.html
layout/reftests/w3c-css/submitted/contain/contain-size-block-001.html
layout/reftests/w3c-css/submitted/contain/contain-size-inline-block-001-ref.html
layout/reftests/w3c-css/submitted/contain/contain-size-inline-block-001.html
layout/reftests/w3c-css/submitted/contain/reftest.list
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -484,16 +484,20 @@ bool
 nsBlockFrame::GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
                                         BaselineSharingGroup aBaselineGroup,
                                         nscoord*             aBaseline) const
 {
   if (aBaselineGroup == BaselineSharingGroup::eFirst) {
     return nsLayoutUtils::GetFirstLineBaseline(aWM, this, aBaseline);
   }
 
+  if (StyleDisplay()->IsContainSize()) {
+    return false;
+  }
+
   for (ConstReverseLineIterator line = LinesRBegin(), line_end = LinesREnd();
        line != line_end; ++line) {
     if (line->IsBlock()) {
       nscoord offset;
       nsIFrame* kid = line->mFirstChild;
       if (kid->GetVerticalAlignBaseline(aWM, &offset)) {
         // Ignore relative positioning for baseline calculations.
         const nsSize& sz = line->mContainerSize;
@@ -696,16 +700,21 @@ nsBlockFrame::GetMinISize(gfxContext *aR
 
   DISPLAY_MIN_WIDTH(this, mMinWidth);
 
   CheckIntrinsicCacheAgainstShrinkWrapState();
 
   if (mMinWidth != NS_INTRINSIC_WIDTH_UNKNOWN)
     return mMinWidth;
 
+  if (StyleDisplay()->IsContainSize()) {
+    mMinWidth = 0;
+    return mMinWidth;
+  }
+
 #ifdef DEBUG
   if (gNoisyIntrinsic) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
     printf(": GetMinISize\n");
   }
   AutoNoisyIndenter indenter(gNoisyIntrinsic);
 #endif
@@ -784,16 +793,21 @@ nsBlockFrame::GetPrefISize(gfxContext *a
 
   DISPLAY_PREF_WIDTH(this, mPrefWidth);
 
   CheckIntrinsicCacheAgainstShrinkWrapState();
 
   if (mPrefWidth != NS_INTRINSIC_WIDTH_UNKNOWN)
     return mPrefWidth;
 
+  if (StyleDisplay()->IsContainSize()) {
+    mPrefWidth = 0;
+    return mPrefWidth;
+  }
+
 #ifdef DEBUG
   if (gNoisyIntrinsic) {
     IndentBy(stdout, gNoiseIndent);
     ListTag(stdout);
     printf(": GetPrefISize\n");
   }
   AutoNoisyIndenter indenter(gNoisyIntrinsic);
 #endif
@@ -1618,16 +1632,27 @@ nsBlockFrame::ComputeFinalSize(const Ref
       // on its own on the last-in-flow, even if we ran out of height
       // here. We need GetSkipSides to check whether we ran out of content
       // height in the current frame, not whether it's last-in-flow.
     }
 
     // Don't carry out a block-end margin when our BSize is fixed.
     aMetrics.mCarriedOutBEndMargin.Zero();
   }
+  else if (aReflowInput.mStyleDisplay->IsContainSize()) {
+    // If we're size-containing and we don't have a specified size, then our
+    // final size should actually be computed from only our border and padding,
+    // as though we were empty.
+    // Hence this case is a simplified version of the case below.
+    nscoord contentBSize = 0;
+    nscoord autoBSize = aReflowInput.ApplyMinMaxBSize(contentBSize);
+    aMetrics.mCarriedOutBEndMargin.Zero();
+    autoBSize += borderPadding.BStartEnd(wm);
+    finalSize.BSize(wm) = autoBSize;
+  }
   else if (aState.mReflowStatus.IsComplete()) {
     nscoord contentBSize = blockEndEdgeOfChildren - borderPadding.BStart(wm);
     nscoord autoBSize = aReflowInput.ApplyMinMaxBSize(contentBSize);
     if (autoBSize != contentBSize) {
       // Our min- or max-bsize value made our bsize change.  Don't carry out
       // our kids' block-end margins.
       aMetrics.mCarriedOutBEndMargin.Zero();
     }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-block-001-ref.html
@@ -0,0 +1,53 @@
+<!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 {
+    border: 1em solid green;
+  }
+  .height-ref {
+    height: 50px;
+    background: lightblue;
+  }
+  .width-ref {
+    width: 50px;
+    background: lightblue;
+  }
+  .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>
+  <br>
+
+  outside before<div></div>outside after
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-block-001.html
@@ -0,0 +1,66 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: size' on block elements should zero the height if unspecified, and should ensure baseline alignment consistency with empty (0x0) objects of the same type. If max-width is specified, 'contain: size' should constrain the block to the specified size.</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-block-001-ref.html">
+  <style>
+  div {
+    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;
+    background: lightblue;
+  }
+  .width {
+    width: 50px;
+    background: lightblue;
+  }
+  .floatLBasic {
+    float: left;
+    width: auto;
+  }
+  .floatLWidth {
+    float: left;
+    width: 50px;
+  }
+  </style>
+</head>
+<body>
+  <div>CSS Test: A size-contained block element with no specified size should render at 0 height regardless of content.</div>
+  <br>
+
+  <div class="minHeight">CSS Test: A size-contained block element with specified min-height should render at given min-height regardless of content.</div>
+  <br>
+
+  <div class="height">CSS Test: A size-contained block element with specified height should render at given height regardless of content.</div>
+  <br>
+
+  <div class="maxWidth">CSS Test: A size-contained block 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 block 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 block 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 block element with specified width and no specified height should render at given width and 0 height regardless of content.</div>
+  <br>
+
+  outside before<div>CSS Test: A size-contained block element should perform baseline alignment as if the container were empty.</div>outside after
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-inline-block-001-ref.html
@@ -0,0 +1,38 @@
+<!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: inline-block;
+    border: 1em solid green;
+  }
+  .height-ref {
+    height: 50px;
+  }
+  .width-ref {
+    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>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-inline-block-001.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: size' on inline- 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="help" href="https://drafts.csswg.org/css-contain/#containment-size">
+  <link rel="match" href="contain-size-inline-block-001-ref.html">
+  <style>
+  div {
+    display: inline-block;
+    contain:size;
+    border: 1em solid green;
+    background: red;
+    color: transparent;
+  }
+  .minHeight {
+    min-height: 50px;
+  }
+  .height {
+    height: 50px;
+  }
+  .minWidth {
+    min-width: 50px;
+  }
+  .width {
+    width: 50px;
+  }
+  </style>
+</head>
+<body>
+  <div>CSS Test: A size-contained inline-block element with no specified size should render at 0 height and 0 width regardless of content.</div>
+  <br>
+
+  outside before<div>CSS Test: A size-contained inline-block element should perform baseline alignment as if the container were empty.</div>outside after
+  <br>
+
+  <div class="minHeight">CSS Test: A size-contained inline-block element with specified min-height should render at given min-height and 0 width regardless of content.</div>
+  <br>
+
+  <div class="height">CSS Test: A size-contained inline-block element with specified height should render at given height and 0 width regardless of content.</div>
+  <br>
+
+  <div class="minWidth">CSS Test: A size-contained inline-block element with specified min-width should render at given min-width and 0 height regardless of content.</div>
+  <br>
+
+  <div class="width">CSS Test: A size-contained inline-block element with specified width 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
@@ -8,8 +8,10 @@ default-preferences pref(layout.css.cont
 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-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