--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -1229,16 +1229,18 @@ exports.CSS_PROPERTIES = {
"-moz-stack-sizing": {
"isInherited": false,
"subproperties": [
"-moz-stack-sizing"
],
"supports": [],
"values": [
"ignore",
+ "ignore-horizontal",
+ "ignore-vertical",
"inherit",
"initial",
"stretch-to-fit",
"unset"
]
},
"-moz-tab-size": {
"isInherited": true,
@@ -3397,16 +3399,18 @@ exports.CSS_PROPERTIES = {
"horizontal",
"horizontal-tb",
"hsl",
"hsla",
"hue",
"icon",
"ideographic",
"ignore",
+ "ignore-horizontal",
+ "ignore-vertical",
"inactive",
"infinite",
"inherit",
"initial",
"inline",
"inline-axis",
"inline-block",
"inline-end",
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -455,17 +455,16 @@ fuzzy-if(skiaContent,2,3) == 339289-1.ht
!= 341043-1b.html 341043-1-ref.html
== 343538-1.html 343538-1-ref.html
== 343540-1.html 343540-1-ref.html
== 345267-1a.html 345267-1-ref.html
== 345267-1b.html 345267-1-ref.html
== 345267-1c.html 345267-1-ref.html
== 345267-1d.html 345267-1-ref.html
!= 345563-sub.xhtml 345563-sup.xhtml
-== 346189-1.xul 346189-1-ref.xul
fuzzy-if(skiaContent,4,2) == 346774-1a.html 346774-1-ref.html
fuzzy-if(skiaContent,4,2) == 346774-1b.html 346774-1-ref.html
fuzzy-if(skiaContent,4,2) == 346774-1c.html 346774-1-ref.html
== 347348-1.xhtml 347348-1-ref.xhtml
== 347496-1.xhtml 347496-1-ref.xhtml
== 347912-1.html 347912-1-ref.html
fails-if(stylo) == 348049-1.xhtml 348049-1-ref.xhtml
== 348516-1.html 348516-1-ref.html
--- a/layout/reftests/xul/reftest.list
+++ b/layout/reftests/xul/reftest.list
@@ -56,16 +56,19 @@ fails-if(!stylo) == object-fit-fill-svg-
== object-fit-scale-down-svg-002.xul object-fit-scale-down-svg-002-ref.html
== object-fit-scale-down-svg-003.xul object-fit-scale-down-svg-003-ref.html
== object-fit-scale-down-svg-004.xul object-fit-scale-down-svg-004-ref.html
== object-fit-scale-down-svg-005.xul object-fit-scale-down-svg-005-ref.html
== object-fit-scale-down-svg-006.xul object-fit-scale-down-svg-006-ref.html
fuzzy-if(webrender,16,20) == object-position-png-001.xul object-position-png-001-ref.html
== object-position-png-002.xul object-position-png-002-ref.html
+== stack-sizing-1.xul stack-sizing-1-ref.xul
+== stack-sizing-2.xul stack-sizing-2-ref.xul
+
# Tests for rendering SVG images in a XUL <treecell>:
# XXXdholbert: These are marked as "random" right now, since they might not
# render the images they trying to test in time for the reftest snapshot, per
# bug 1218954.
skip == treecell-image-svg-1a.xul treecell-image-svg-1-ref.xul # bug 1218954
skip == treecell-image-svg-1b.xul treecell-image-svg-1-ref.xul # bug 1218954
== treechildren-padding-percent-1.xul treechildren-padding-percent-1-ref.xul
rename from layout/reftests/bugs/346189-1-ref.xul
rename to layout/reftests/xul/stack-sizing-1-ref.xul
rename from layout/reftests/bugs/346189-1.xul
rename to layout/reftests/xul/stack-sizing-1.xul
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/stack-sizing-2-ref.xul
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="400"
+ height="600"
+ align="start">
+
+<box style="background: red; width: 20px; height: 20px;"/>
+
+<box style="background: green; width: 10px; height: 20px;"/>
+
+<box style="background: blue; width: 20px; height: 10px;"/>
+
+<box style="background: yellow; width: 10px; height: 10px;"/>
+
+</window>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/xul/stack-sizing-2.xul
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+
+<window
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ width="400"
+ height="600"
+ align="start">
+
+<!-- stretch-to-fit: both width and height are considered. -->
+<stack style="background: red;">
+ <box style="width: 10px; height: 10px;"/>
+ <box style="-moz-stack-sizing: stretch-to-fit; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore-horizontal: width is not considered, height is considered. -->
+<stack style="background: green;">
+ <box style="width: 10px; height: 10px;"/>
+ <box style="-moz-stack-sizing: ignore-horizontal; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore-vertical: width is considered, height is not considered. -->
+<stack style="background: blue;">
+ <box style="width: 10px; height: 10px;"/>
+ <box style="-moz-stack-sizing: ignore-vertical; width: 20px; height: 20px;"/>
+</stack>
+
+<!-- ignore: neither width or height are considered. -->
+<stack style="background: yellow;">
+ <box style="width: 10px; height: 10px;"/>
+ <box style="-moz-stack-sizing: ignore; width: 20px; height: 20px;"/>
+</stack>
+
+</window>
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -307,16 +307,18 @@ CSS_KEY(historical-forms, historical_for
CSS_KEY(historical-ligatures, historical_ligatures)
CSS_KEY(horizontal, horizontal)
CSS_KEY(horizontal-tb, horizontal_tb)
CSS_KEY(hue, hue)
CSS_KEY(hue-rotate, hue_rotate)
CSS_KEY(hz, hz)
CSS_KEY(icon, icon)
CSS_KEY(ignore, ignore)
+CSS_KEY(ignore-horizontal, ignore_horizontal)
+CSS_KEY(ignore-vertical, ignore_vertical)
CSS_KEY(in, in)
CSS_KEY(interlace, interlace)
CSS_KEY(inactive, inactive)
CSS_KEY(inactiveborder, inactiveborder)
CSS_KEY(inactivecaption, inactivecaption)
CSS_KEY(inactivecaptiontext, inactivecaptiontext)
CSS_KEY(infinite, infinite)
CSS_KEY(infobackground, infobackground)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1961,18 +1961,20 @@ const KTableEntry nsCSSProps::kScrollBeh
const KTableEntry nsCSSProps::kScrollSnapTypeKTable[] = {
{ eCSSKeyword_none, NS_STYLE_SCROLL_SNAP_TYPE_NONE },
{ eCSSKeyword_mandatory, NS_STYLE_SCROLL_SNAP_TYPE_MANDATORY },
{ eCSSKeyword_proximity, NS_STYLE_SCROLL_SNAP_TYPE_PROXIMITY },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kStackSizingKTable[] = {
- { eCSSKeyword_ignore, NS_STYLE_STACK_SIZING_IGNORE },
- { eCSSKeyword_stretch_to_fit, NS_STYLE_STACK_SIZING_STRETCH_TO_FIT },
+ { eCSSKeyword_ignore, StyleStackSizing::Ignore },
+ { eCSSKeyword_stretch_to_fit, StyleStackSizing::StretchToFit },
+ { eCSSKeyword_ignore_horizontal, StyleStackSizing::IgnoreHorizontal },
+ { eCSSKeyword_ignore_vertical, StyleStackSizing::IgnoreVertical },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kTableLayoutKTable[] = {
{ eCSSKeyword_auto, NS_STYLE_TABLE_LAYOUT_AUTO },
{ eCSSKeyword_fixed, NS_STYLE_TABLE_LAYOUT_FIXED },
{ eCSSKeyword_UNKNOWN, -1 }
};
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1077,18 +1077,18 @@ nsComputedDOMStyle::DoGetBottom()
{
return GetOffsetWidthFor(eSideBottom);
}
already_AddRefed<CSSValue>
nsComputedDOMStyle::DoGetStackSizing()
{
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
- val->SetIdent(StyleXUL()->mStretchStack ? eCSSKeyword_stretch_to_fit :
- eCSSKeyword_ignore);
+ val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mStackSizing,
+ nsCSSProps::kStackSizingKTable));
return val.forget();
}
void
nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
nscolor aColor)
{
nsROCSSPrimitiveValue *red = new nsROCSSPrimitiveValue;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1496,16 +1496,17 @@ struct SetEnumValueHelper
DEFINE_ENUM_CLASS_SETTER(StyleBoxOrient, Horizontal, Vertical)
DEFINE_ENUM_CLASS_SETTER(StyleBoxPack, Start, Justify)
DEFINE_ENUM_CLASS_SETTER(StyleBoxSizing, Content, Border)
DEFINE_ENUM_CLASS_SETTER(StyleClear, None, Both)
DEFINE_ENUM_CLASS_SETTER(StyleFillRule, Nonzero, Evenodd)
DEFINE_ENUM_CLASS_SETTER(StyleFloat, None, InlineEnd)
DEFINE_ENUM_CLASS_SETTER(StyleFloatEdge, ContentBox, MarginBox)
DEFINE_ENUM_CLASS_SETTER(StyleHyphens, None, Auto)
+ DEFINE_ENUM_CLASS_SETTER(StyleStackSizing, Ignore, IgnoreVertical)
DEFINE_ENUM_CLASS_SETTER(StyleTextJustify, None, InterCharacter)
DEFINE_ENUM_CLASS_SETTER(StyleUserFocus, None, SelectMenu)
DEFINE_ENUM_CLASS_SETTER(StyleUserSelect, None, MozText)
DEFINE_ENUM_CLASS_SETTER(StyleUserInput, None, Auto)
DEFINE_ENUM_CLASS_SETTER(StyleUserModify, ReadOnly, WriteOnly)
DEFINE_ENUM_CLASS_SETTER(StyleWindowDragging, Default, NoDrag)
DEFINE_ENUM_CLASS_SETTER(StyleOrient, Inline, Vertical)
DEFINE_ENUM_CLASS_SETTER(StyleGeometryBox, BorderBox, ViewBox)
@@ -9083,27 +9084,21 @@ nsRuleNode::ComputeXULData(void* aStartS
StyleBoxPack::Start);
// box-ordinal-group: integer, inherit, initial
SetValue(*aRuleData->ValueForBoxOrdinalGroup(),
xul->mBoxOrdinal, conditions,
SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
parentXUL->mBoxOrdinal, 1);
- const nsCSSValue* stackSizingValue = aRuleData->ValueForStackSizing();
- if (eCSSUnit_Inherit == stackSizingValue->GetUnit()) {
- conditions.SetUncacheable();
- xul->mStretchStack = parentXUL->mStretchStack;
- } else if (eCSSUnit_Initial == stackSizingValue->GetUnit() ||
- eCSSUnit_Unset == stackSizingValue->GetUnit()) {
- xul->mStretchStack = true;
- } else if (eCSSUnit_Enumerated == stackSizingValue->GetUnit()) {
- xul->mStretchStack = stackSizingValue->GetIntValue() ==
- NS_STYLE_STACK_SIZING_STRETCH_TO_FIT;
- }
+ SetValue(*aRuleData->ValueForStackSizing(),
+ xul->mStackSizing, conditions,
+ SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
+ parentXUL->mStackSizing,
+ StyleStackSizing::StretchToFit);
COMPUTE_END_RESET(XUL, xul)
}
const void*
nsRuleNode::ComputeColumnData(void* aStartStruct,
const nsRuleData* aRuleData,
nsStyleContext* aContext,
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -153,16 +153,24 @@ enum class StyleShapeRadius : uint8_t {
// Shape source type
enum class StyleShapeSourceType : uint8_t {
None,
URL,
Shape,
Box,
};
+// -moz-stack-sizing
+enum class StyleStackSizing : uint8_t {
+ Ignore,
+ StretchToFit,
+ IgnoreHorizontal,
+ IgnoreVertical,
+};
+
// text-justify
enum class StyleTextJustify : uint8_t {
None,
Auto,
InterWord,
InterCharacter,
};
@@ -217,20 +225,16 @@ enum class StyleWindowDragging : uint8_t
// orient
enum class StyleOrient : uint8_t {
Inline,
Block,
Horizontal,
Vertical,
};
-// stack-sizing
-#define NS_STYLE_STACK_SIZING_IGNORE 0
-#define NS_STYLE_STACK_SIZING_STRETCH_TO_FIT 1
-
// Azimuth - See nsStyleAural
#define NS_STYLE_AZIMUTH_LEFT_SIDE 0x00
#define NS_STYLE_AZIMUTH_FAR_LEFT 0x01
#define NS_STYLE_AZIMUTH_LEFT 0x02
#define NS_STYLE_AZIMUTH_CENTER_LEFT 0x03
#define NS_STYLE_AZIMUTH_CENTER 0x04
#define NS_STYLE_AZIMUTH_CENTER_RIGHT 0x05
#define NS_STYLE_AZIMUTH_RIGHT 0x06
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -739,48 +739,48 @@ nsStyleList::sNoneQuotes;
//
nsStyleXUL::nsStyleXUL(const nsPresContext* aContext)
: mBoxFlex(0.0f)
, mBoxOrdinal(1)
, mBoxAlign(StyleBoxAlign::Stretch)
, mBoxDirection(StyleBoxDirection::Normal)
, mBoxOrient(StyleBoxOrient::Horizontal)
, mBoxPack(StyleBoxPack::Start)
- , mStretchStack(true)
+ , mStackSizing(StyleStackSizing::StretchToFit)
{
MOZ_COUNT_CTOR(nsStyleXUL);
}
nsStyleXUL::~nsStyleXUL()
{
MOZ_COUNT_DTOR(nsStyleXUL);
}
nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
: mBoxFlex(aSource.mBoxFlex)
, mBoxOrdinal(aSource.mBoxOrdinal)
, mBoxAlign(aSource.mBoxAlign)
, mBoxDirection(aSource.mBoxDirection)
, mBoxOrient(aSource.mBoxOrient)
, mBoxPack(aSource.mBoxPack)
- , mStretchStack(aSource.mStretchStack)
+ , mStackSizing(aSource.mStackSizing)
{
MOZ_COUNT_CTOR(nsStyleXUL);
}
nsChangeHint
nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
{
if (mBoxAlign == aNewData.mBoxAlign &&
mBoxDirection == aNewData.mBoxDirection &&
mBoxFlex == aNewData.mBoxFlex &&
mBoxOrient == aNewData.mBoxOrient &&
mBoxPack == aNewData.mBoxPack &&
mBoxOrdinal == aNewData.mBoxOrdinal &&
- mStretchStack == aNewData.mStretchStack) {
+ mStackSizing == aNewData.mStackSizing) {
return nsChangeHint(0);
}
if (mBoxOrdinal != aNewData.mBoxOrdinal) {
return nsChangeHint_ReconstructFrame;
}
return NS_STYLE_HINT_REFLOW;
}
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -3308,17 +3308,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
nsChangeHint CalcDifference(const nsStyleXUL& aNewData) const;
float mBoxFlex; // [reset] see nsStyleConsts.h
uint32_t mBoxOrdinal; // [reset] see nsStyleConsts.h
mozilla::StyleBoxAlign mBoxAlign; // [reset]
mozilla::StyleBoxDirection mBoxDirection; // [reset]
mozilla::StyleBoxOrient mBoxOrient; // [reset]
mozilla::StyleBoxPack mBoxPack; // [reset]
- bool mStretchStack; // [reset] see nsStyleConsts.h
+ mozilla::StyleStackSizing mStackSizing; // [reset] see nsStyleConsts.h
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
{
explicit nsStyleColumn(const nsPresContext* aContext);
nsStyleColumn(const nsStyleColumn& aSource);
~nsStyleColumn();
void FinishStyle(nsPresContext* aPresContext) {}
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -1598,17 +1598,17 @@ var gCSSProperties = {
other_values: [ "both", "horizontal", "vertical" ],
invalid_values: []
},
"-moz-stack-sizing": {
domProp: "MozStackSizing",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "stretch-to-fit" ],
- other_values: [ "ignore" ],
+ other_values: [ "ignore", "ignore-horizontal", "ignore-vertical" ],
invalid_values: []
},
"-moz-tab-size": {
domProp: "MozTabSize",
inherited: true,
type: CSS_TYPE_LONGHAND,
initial_values: [ "8" ],
other_values: [ "0", "2.5", "3", "99", "12000", "0px", "1em", "calc(1px + 1em)", "calc(1px - 2px)", "calc(1 + 1)", "calc(-2.5)" ],
--- a/layout/xul/nsStackLayout.cpp
+++ b/layout/xul/nsStackLayout.cpp
@@ -60,25 +60,34 @@ nsStackLayout::nsStackLayout()
nsSize
nsStackLayout::GetXULPrefSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize prefSize (0, 0);
nsIFrame* child = nsBox::GetChildXULBox(aBox);
while (child) {
- if (child->StyleXUL()->mStretchStack) {
+ auto stackSizing = child->StyleXUL()->mStackSizing;
+ if (stackSizing != StyleStackSizing::Ignore) {
nsSize pref = child->GetXULPrefSize(aState);
AddMargin(child, pref);
nsMargin offset;
GetOffset(child, offset);
pref.width += offset.LeftRight();
pref.height += offset.TopBottom();
- AddLargestSize(prefSize, pref);
+
+ if (pref.width > prefSize.width &&
+ stackSizing != StyleStackSizing::IgnoreHorizontal) {
+ prefSize.width = pref.width;
+ }
+ if (pref.height > prefSize.height &&
+ stackSizing != StyleStackSizing::IgnoreVertical) {
+ prefSize.height = pref.height;
+ }
}
child = nsBox::GetNextXULBox(child);
}
AddBorderAndPadding(aBox, prefSize);
return prefSize;
@@ -86,25 +95,34 @@ nsStackLayout::GetXULPrefSize(nsIFrame*
nsSize
nsStackLayout::GetXULMinSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize minSize (0, 0);
nsIFrame* child = nsBox::GetChildXULBox(aBox);
while (child) {
- if (child->StyleXUL()->mStretchStack) {
+ auto stackSizing = child->StyleXUL()->mStackSizing;
+ if (stackSizing != StyleStackSizing::Ignore) {
nsSize min = child->GetXULMinSize(aState);
AddMargin(child, min);
nsMargin offset;
GetOffset(child, offset);
min.width += offset.LeftRight();
min.height += offset.TopBottom();
- AddLargestSize(minSize, min);
+
+ if (min.width > minSize.width &&
+ stackSizing != StyleStackSizing::IgnoreHorizontal) {
+ minSize.width = min.width;
+ }
+ if (min.height > minSize.height &&
+ stackSizing != StyleStackSizing::IgnoreVertical) {
+ minSize.height = min.height;
+ }
}
child = nsBox::GetNextXULBox(child);
}
AddBorderAndPadding(aBox, minSize);
return minSize;
@@ -112,28 +130,37 @@ nsStackLayout::GetXULMinSize(nsIFrame* a
nsSize
nsStackLayout::GetXULMaxSize(nsIFrame* aBox, nsBoxLayoutState& aState)
{
nsSize maxSize (NS_INTRINSICSIZE, NS_INTRINSICSIZE);
nsIFrame* child = nsBox::GetChildXULBox(aBox);
while (child) {
- if (child->StyleXUL()->mStretchStack) {
+ auto stackSizing = child->StyleXUL()->mStackSizing;
+ if (stackSizing != StyleStackSizing::Ignore) {
nsSize min = child->GetXULMinSize(aState);
nsSize max = child->GetXULMaxSize(aState);
max = nsBox::BoundsCheckMinMax(min, max);
AddMargin(child, max);
nsMargin offset;
GetOffset(child, offset);
max.width += offset.LeftRight();
max.height += offset.TopBottom();
- AddSmallestSize(maxSize, max);
+
+ if (max.width < maxSize.width &&
+ stackSizing != StyleStackSizing::IgnoreHorizontal) {
+ maxSize.width = max.width;
+ }
+ if (max.height < maxSize.height &&
+ stackSizing != StyleStackSizing::IgnoreVertical) {
+ maxSize.height = max.height;
+ }
}
child = nsBox::GetNextXULBox(child);
}
AddBorderAndPadding(aBox, maxSize);
return maxSize;
@@ -340,34 +367,37 @@ nsStackLayout::XULLayout(nsIFrame* aBox,
// Flow the child.
child->XULLayout(aState);
// Get the child's new rect.
childRect = child->GetRect();
childRect.Inflate(margin);
- if (child->StyleXUL()->mStretchStack) {
+ auto stackSizing = child->StyleXUL()->mStackSizing;
+ if (stackSizing != StyleStackSizing::Ignore) {
// Did the child push back on us and get bigger?
- if (offset.LeftRight() + childRect.width > clientRect.width) {
+ if (offset.LeftRight() + childRect.width > clientRect.width &&
+ stackSizing != StyleStackSizing::IgnoreHorizontal) {
clientRect.width = childRect.width + offset.LeftRight();
grow = true;
}
- if (offset.TopBottom() + childRect.height > clientRect.height) {
+ if (offset.TopBottom() + childRect.height > clientRect.height &&
+ stackSizing != StyleStackSizing::IgnoreVertical) {
clientRect.height = childRect.height + offset.TopBottom();
grow = true;
}
}
}
child = nsBox::GetNextXULBox(child);
}
} while (grow);
-
+
// if some HTML inside us got bigger we need to force ourselves to
// get bigger
nsRect bounds(aBox->GetRect());
nsMargin bp;
aBox->GetXULBorderAndPadding(bp);
clientRect.Inflate(bp);
if (clientRect.width > bounds.width || clientRect.height > bounds.height)