Bug 1467209 - Implement contain:size for HTMLButtonControlFrame. draft
authorMorgan Rae Reschenberg <mreschenberg@mozilla.com>
Thu, 07 Jun 2018 10:13:16 -0700
changeset 811586 c41b31626bfda3d8e4cc6ffc00788b1e43fb12f4
parent 806725 9941eb8c3b29d152851220b5d9791326c35e1c68
child 811587 eec53afa1e151dac6f953c3abc9d3eb886a6342e
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 HTMLButtonControlFrame. MozReview-Commit-ID: Cwfni9ieX74
layout/forms/nsHTMLButtonControlFrame.cpp
layout/reftests/w3c-css/submitted/contain/contain-size-button-001-ref.html
layout/reftests/w3c-css/submitted/contain/contain-size-button-001.html
layout/reftests/w3c-css/submitted/contain/reftest.list
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -141,36 +141,40 @@ nsHTMLButtonControlFrame::BuildDisplayLi
   DisplaySelectionOverlay(aBuilder, aLists.Content());
 }
 
 nscoord
 nsHTMLButtonControlFrame::GetMinISize(gfxContext* aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
-
-  nsIFrame* kid = mFrames.FirstChild();
-  result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
-                                                kid,
-                                                nsLayoutUtils::MIN_ISIZE);
-
+  if (StyleDisplay()->IsContainSize()) {
+    result = 0;
+  } else {
+    nsIFrame* kid = mFrames.FirstChild();
+    result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+                                                  kid,
+                                                  nsLayoutUtils::MIN_ISIZE);
+  }
   return result;
 }
 
 nscoord
 nsHTMLButtonControlFrame::GetPrefISize(gfxContext* aRenderingContext)
 {
   nscoord result;
   DISPLAY_PREF_WIDTH(this, result);
-
-  nsIFrame* kid = mFrames.FirstChild();
-  result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
-                                                kid,
-                                                nsLayoutUtils::PREF_ISIZE);
-
+  if (StyleDisplay()->IsContainSize()) {
+    result = 0;
+  } else {
+    nsIFrame* kid = mFrames.FirstChild();
+    result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
+                                                  kid,
+                                                  nsLayoutUtils::PREF_ISIZE);
+  }
   return result;
 }
 
 void
 nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
                                  ReflowOutput& aDesiredSize,
                                  const ReflowInput& aReflowInput,
                                  nsReflowStatus& aStatus)
@@ -256,16 +260,21 @@ nsHTMLButtonControlFrame::ReflowButtonCo
              "We gave button-contents frame unconstrained available height, "
              "so it should be complete");
 
   // Compute the button's content-box size:
   LogicalSize buttonContentBox(wm);
   if (aButtonReflowInput.ComputedBSize() != NS_INTRINSICSIZE) {
     // Button has a fixed block-size -- that's its content-box bSize.
     buttonContentBox.BSize(wm) = aButtonReflowInput.ComputedBSize();
+  } else if (aButtonReflowInput.mStyleDisplay->IsContainSize()) {
+    // Button is intrinsically sized and has size containment.
+    // It should have a BSize that is either zero or the minimum
+    // specified BSize.
+    buttonContentBox.BSize(wm) = aButtonReflowInput.ComputedMinBSize();
   } else {
     // Button is intrinsically sized -- it should shrinkwrap the
     // button-contents' bSize:
     buttonContentBox.BSize(wm) = contentsDesiredSize.BSize(wm);
 
     // Make sure we obey min/max-bSize in the case when we're doing intrinsic
     // sizing (we get it for free when we have a non-intrinsic
     // aButtonReflowInput.ComputedBSize()).  Note that we do this before
@@ -273,16 +282,18 @@ nsHTMLButtonControlFrame::ReflowButtonCo
     // mComputedMinBSize are content bSizes.
     buttonContentBox.BSize(wm) =
       NS_CSS_MINMAX(buttonContentBox.BSize(wm),
                     aButtonReflowInput.ComputedMinBSize(),
                     aButtonReflowInput.ComputedMaxBSize());
   }
   if (aButtonReflowInput.ComputedISize() != NS_INTRINSICSIZE) {
     buttonContentBox.ISize(wm) = aButtonReflowInput.ComputedISize();
+  } else if (aButtonReflowInput.mStyleDisplay->IsContainSize()) {
+    buttonContentBox.ISize(wm) = aButtonReflowInput.ComputedMinISize();
   } else {
     buttonContentBox.ISize(wm) = contentsDesiredSize.ISize(wm);
     buttonContentBox.ISize(wm) =
       NS_CSS_MINMAX(buttonContentBox.ISize(wm),
                     aButtonReflowInput.ComputedMinISize(),
                     aButtonReflowInput.ComputedMaxISize());
   }
 
@@ -317,17 +328,19 @@ nsHTMLButtonControlFrame::ReflowButtonCo
   aButtonDesiredSize.SetSize(wm,
     LogicalSize(wm, aButtonReflowInput.ComputedISize() + clbp.IStartEnd(wm),
                     buttonContentBox.BSize(wm) + clbp.BStartEnd(wm)));
 
   //  * Button's ascent is its child's ascent, plus the child's block-offset
   // within our frame... unless it's orthogonal, in which case we'll use the
   // contents inline-size as an approximation for now.
   // XXX is there a better strategy? should we include border-padding?
-  if (aButtonDesiredSize.GetWritingMode().IsOrthogonalTo(wm)) {
+  if (aButtonReflowInput.mStyleDisplay->IsContainSize()) {
+    aButtonDesiredSize.SetBlockStartAscent(childPos.B(wm));
+  } else if (aButtonDesiredSize.GetWritingMode().IsOrthogonalTo(wm)) {
     aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.ISize(wm));
   } else {
     aButtonDesiredSize.SetBlockStartAscent(contentsDesiredSize.BlockStartAscent() +
                                            childPos.B(wm));
   }
 
   aButtonDesiredSize.SetOverflowAreasToDesiredBounds();
 }
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-button-001-ref.html
@@ -0,0 +1,62 @@
+<!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>
+  button {
+    border: 1em solid green;
+  }
+  .width-ref {
+    width: 50px;
+  }
+  .floatLBasic-ref {
+    float: left;
+  }
+  .floatLWidth-ref {
+    float: left;
+    width: 50px;
+    height: 0;
+  }
+  .iFlexBasic-ref {
+    display: inline-flex;
+  }
+  .iFlexWidth-ref {
+    display: inline-flex;
+    width: 50px;
+    height: 0;
+  }
+  .orthog-ref {
+    writing-mode: vertical-lr;
+  }
+  </style>
+</head>
+<body>
+  <button></button>
+  <br>
+
+  <button class="floatLBasic-ref"></button>
+  <br>
+
+  <button class="floatLWidth-ref"></button>
+  <br>
+
+  <button class="iFlexBasic-ref"></button>
+  <br>
+
+  <button class="iFlexWidth-ref"></button>
+  <br>
+
+  outside before<button></button>outside after
+  <br>
+
+  <button class="width-ref"></button>
+  <br>
+
+  <button class="width-ref"></button>
+  <br>
+
+  s<button class="orthog-ref"></button>endtext
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-button-001.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>CSS Test: 'contain: size' on buttons 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-button-001-ref.html">
+  <style>
+  button {
+    contain: size;
+    border: 1em solid green;
+    background: red;
+    color: transparent;
+  }
+  .minWidth {
+    min-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;
+  }
+  .orthog {
+    writing-mode: vertical-lr;
+  }
+  </style>
+</head>
+<body>
+  <button>CSS Test: A size-contained button with no specified size should render at 0 height regardless of content.</button>
+  <br>
+
+  <button class="floatLBasic">CSS Test: A size-contained floated button with auto width and no specified height should render at 0px by 0px regardless of content.</button>
+  <br>
+
+  <button class="floatLWidth">CSS Test: A size-contained floated button with specified width and no specified height should render at given width and 0 height regardless of content.</button>
+  <br>
+
+  <button class="iFlexBasic">CSS Test: A size-contained inline-flex button with auto width and no specified height should render at 0px by 0px regardless of content.</button>
+  <br>
+
+  <button class="iFlexWidth">CSS Test: A size-contained inline-flex button with specified width and no specified height should render at given width and 0 height regardless of content.</button>
+  <br>
+
+  outside before<button>CSS Test: A size-contained button should perform baseline alignment as if the container were empty.</button>outside after
+  <br>
+
+  <button class="minWidth">CSS Test: A size-contained button with specified min-width should render at given min-width and zero height regardless of content.</button>
+  <br>
+
+  <button class="width">CSS Test: A size-contained button with specified width should render at given width and zero height regardless of content.</button>
+  <br>
+
+  s<button class="orthog">CSS Test: A size-contained button with vertical text should perform baseline alignment as if the container were empty.</button>endtext
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -7,8 +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-button-001.html contain-size-button-001-ref.html