Bug 1467209 - Implement contain:size for HTMLButtonControlFrame.
MozReview-Commit-ID: Jsjs3jxy4z3
--- 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,24 @@ 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()) {
+ // If we're size-contained, we should pretend our contents had 0 height
+ // (as they would, if we had no children). This case is identical to the
+ // final else case, but uses only our specified button height for ascent
+ // (ie. it ignores the height returned in contentsDesiredSize).
+ nscoord containAscent = (buttonContentBox.BSize(wm) / 2) + clbp.BStart(wm);
+ aButtonDesiredSize.SetBlockStartAscent(containAscent);
+ } 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,73 @@
+<!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;
+ }
+ .height-ref {
+ height: 50px;
+ background: lightblue;
+ }
+ .floatLBasic-ref {
+ float: left;
+ }
+ .floatLWidth-ref {
+ float: left;
+ width: 50px;
+ }
+ .iFlexBasic-ref {
+ display: inline-flex;
+ }
+ .iFlexWidth-ref {
+ display: inline-flex;
+ width: 50px;
+ }
+ .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>
+
+ <button class="height-ref"></button>
+ <br>
+
+ <button class="height-ref"></button>
+ <br>
+
+ s<button class="orthog-ref"></button>endtext
+ <br>
+
+ <button class="height-ref width-ref">inside</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/w3c-css/submitted/contain/contain-size-button-001.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>CSS Test: 'contain: size' on buttons should cause them to be sized and baseline-aligned as if they had no contents.</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-button-001-ref.html">
+ <style>
+ button {
+ contain: size;
+ border: 1em solid green;
+ background: red;
+ }
+ .innerContents {
+ color: transparent;
+ height: 100px;
+ width: 100px;
+ }
+ .minWidth {
+ min-width: 50px;
+ }
+ .width {
+ width: 50px;
+ }
+ .minHeight {
+ min-height: 50px;
+ background: lightblue;
+ }
+ .height {
+ height: 50px;
+ background: lightblue;
+ }
+ .floatLBasic {
+ float: left;
+ }
+ .floatLWidth {
+ float: left;
+ width: 50px;
+ }
+ .iFlexBasic {
+ display: inline-flex;
+ }
+ .iFlexWidth {
+ display: inline-flex;
+ width: 50px;
+ }
+ .orthog {
+ writing-mode: vertical-lr;
+ }
+ </style>
+</head>
+<body>
+ <!--CSS Test: A size-contained button with no specified size should render at 0 height regardless of content.-->
+ <button><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained floated button with no specified size should render at 0px by 0px regardless of content.-->
+ <button class="floatLBasic"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--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 class="floatLWidth"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained inline-flex button with no specified size should render at 0px by 0px regardless of content.-->
+ <button class="iFlexBasic"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--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 class="iFlexWidth"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained button should perform baseline alignment as if the container were empty.-->
+ outside before<button><div class="innerContents">inner</div></button>outside after
+ <br>
+
+ <!--CSS Test: A size-contained button with specified min-width should render at given min-width and zero height regardless of content.-->
+ <button class="minWidth"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained button with specified width should render at given width and zero height regardless of content.-->
+ <button class="width"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained button with specified min-height should render at given min-height regardless of content.-->
+ <button class="minHeight"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained button with specified height should render at given height regardless of content.-->
+ <button class="height"><div class="innerContents">inner</div></button>
+ <br>
+
+ <!--CSS Test: A size-contained button with vertical text should perform baseline alignment as if the container were empty.-->
+ s<button class="orthog"><div class="innerContents">inner</div></button>endtext
+ <br>
+
+ <!--CSS Test: A size-contained button with inner text should layout the text in the same manner as a container of the same type with identical contents.-->
+ <button class="height width">inside</button>
+</body>
+</html>
--- a/layout/reftests/w3c-css/submitted/contain/reftest.list
+++ b/layout/reftests/w3c-css/submitted/contain/reftest.list
@@ -12,9 +12,10 @@ pref(layout.css.overflow-clip-box.enable
== contain-paint-formatting-context-margin-001.html contain-paint-formatting-context-margin-001-ref.html
== contain-paint-ignored-cases-internal-table-001a.html contain-paint-ignored-cases-internal-table-001-ref.html
== contain-paint-ignored-cases-internal-table-001b.html contain-paint-ignored-cases-internal-table-001-ref.html
== contain-paint-ignored-cases-no-principal-box-001.html contain-paint-ignored-cases-no-principal-box-001-ref.html
== contain-paint-ignored-cases-ruby-containing-block-001.html contain-paint-ignored-cases-ruby-containing-block-001-ref.html
== contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html contain-paint-ignored-cases-ruby-stacking-and-clipping-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-multicol-001.html contain-size-multicol-001-ref.html