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 809301 5024133d58932df1c663a178fb8934fe57fd2222
parent 809300 e2395e4e08eb25a104f63eca8c2d6e98e9f13ae5
child 809302 16783b5defbf700afda318941b73d18bd792a0fc
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 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
@@ -470,27 +470,30 @@ nsBlockFrame::InvalidateFrameWithRect(co
     return;
   }
   nsContainerFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey, aRebuildDisplayItems);
 }
 
 nscoord
 nsBlockFrame::GetLogicalBaseline(WritingMode aWM) const
 {
+  if (StyleDisplay()->IsContainSize()) {
+    return BSize(aWM);
+  }
   auto lastBaseline =
     BaselineBOffset(aWM, BaselineSharingGroup::eLast, AlignmentContext::eInline);
   return BSize(aWM) - lastBaseline;
 }
 
 bool
 nsBlockFrame::GetNaturalBaselineBOffset(mozilla::WritingMode aWM,
                                         BaselineSharingGroup aBaselineGroup,
                                         nscoord*             aBaseline) const
 {
-  if (aBaselineGroup == BaselineSharingGroup::eFirst) {
+  if (aBaselineGroup == BaselineSharingGroup::eFirst || StyleDisplay()->IsContainSize()) {
     return nsLayoutUtils::GetFirstLineBaseline(aWM, this, aBaseline);
   }
 
   for (ConstReverseLineIterator line = LinesRBegin(), line_end = LinesREnd();
        line != line_end; ++line) {
     if (line->IsBlock()) {
       nscoord offset;
       nsIFrame* kid = line->mFirstChild;
@@ -696,16 +699,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 +792,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 +1631,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,69 @@
+<!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;
+  }
+  .iFlexBasic-ref {
+    vertical-align: top;
+    display: inline-flex;
+    width: 0;
+  }
+  .iFlexWidth-ref {
+    vertical-align: top;
+    display: inline-flex;
+    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>
+
+  <div class="iFlexBasic-ref"></div>
+  <br>
+
+  <div class="iFlexWidth-ref"></div>
+  <br>
+
+  outside before<div></div>outside after
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-block-001.html
@@ -0,0 +1,79 @@
+<!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="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;
+  }
+  .iFlexBasic {
+    display: inline-flex;
+    width: auto;
+  }
+  .iFlexWidth {
+    display: inline-flex;
+    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>
+
+  <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>
+
+  <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>
+  <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>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-inline-block-001-ref.html
@@ -0,0 +1,70 @@
+<!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;
+  }
+  .floatLBasic-ref {
+    float: left;
+    width: 0;
+    height: 0;
+  }
+  .floatLWidth-ref {
+    float: left;
+    width: 50px;
+    height: 0;
+  }
+  .iFlexBasic-ref {
+    display: inline-flex;
+    width: 0;
+    height: 0;
+  }
+  .iFlexWidth-ref {
+    display: inline-flex;
+    width: 50px;
+    height: 0;
+  }
+  </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>
+
+  <div class="iFlexBasic-ref"></div>
+  <br>
+
+  <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-inline-block-001.html
@@ -0,0 +1,76 @@
+<!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="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;
+  }
+  .floatLBasic {
+    float: left;
+    width: auto;
+  }
+  .floatLWidth {
+    float: left;
+    width: 50px;
+  }
+  .iFlex{
+    display: inline-flex;
+    width: auto;
+  }
+  .iFlexWidth {
+    display: inline-flex;
+    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>
+  <br>
+
+  <div class="floatLBasic">CSS Test: A size-contained floated inline-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 inline-block element with specified width and no specified height should render at given width and 0 height regardless of content.</div>
+  <br>
+
+  <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>
+
+  <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,9 +7,11 @@ 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