Bug 1176782 part 6 - [css-align] Implement additional syntax and values for the 'align-content' property in the style system. r=cam
authorMats Palmgren <mats@mozilla.com>
Tue, 03 Nov 2015 15:18:06 +0100
changeset 270941 5ed5ee646acd814ac782873ee73194e843695870
parent 270940 ba69ab935f538911ff97764e9f284d7621d663d1
child 270942 075f3a69cc48715bb4b8cae7577b95f39298666f
push id67508
push usermpalmgren@mozilla.com
push dateTue, 03 Nov 2015 14:18:18 +0000
treeherdermozilla-inbound@56aebef6afdf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscam
bugs1176782
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1176782 part 6 - [css-align] Implement additional syntax and values for the 'align-content' property in the style system. r=cam
layout/generic/nsFlexContainerFrame.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/test/property_database.js
--- a/layout/generic/nsFlexContainerFrame.cpp
+++ b/layout/generic/nsFlexContainerFrame.cpp
@@ -3734,17 +3734,18 @@ nsFlexContainerFrame::DoFlexLayout(nsPre
   const nscoord contentBoxCrossSize =
     ComputeCrossSize(aReflowState, aAxisTracker, sumLineCrossSizes,
                      aAvailableBSizeForContent, &isCrossSizeDefinite, aStatus);
 
   // Set up state for cross-axis alignment, at a high level (outside the
   // scope of a particular flex line)
   CrossAxisPositionTracker
     crossAxisPosnTracker(lines.getFirst(),
-                         aReflowState.mStylePosition->mAlignContent,
+                         aReflowState.mStylePosition->ComputedAlignContent(
+                           aReflowState.mStyleDisplay),
                          contentBoxCrossSize, isCrossSizeDefinite,
                          aAxisTracker);
 
   // Now that we know the cross size of each line (including
   // "align-content:stretch" adjustments, from the CrossAxisPositionTracker
   // constructor), we can create struts for any flex items with
   // "visibility: collapse" (and restart flex layout).
   if (aStruts.IsEmpty()) { // (Don't make struts if we already did)
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -10627,16 +10627,18 @@ CSSParserImpl::ParsePropertyByFunction(n
                               eCSSProperty_grid_column_end);
   case eCSSProperty_grid_row:
     return ParseGridColumnRow(eCSSProperty_grid_row_start,
                               eCSSProperty_grid_row_end);
   case eCSSProperty_grid_area:
     return ParseGridArea();
   case eCSSProperty_image_region:
     return ParseRect(eCSSProperty_image_region);
+  case eCSSProperty_align_content:
+    return ParseAlignJustifyContent(aPropID);
   case eCSSProperty_align_items:
     return ParseAlignItemsSelfJustifySelf(aPropID);
   case eCSSProperty_align_self:
     return ParseAlignItemsSelfJustifySelf(aPropID);
   case eCSSProperty_justify_content:
     return ParseAlignJustifyContent(aPropID);
   case eCSSProperty_justify_items:
     return ParseJustifyItems();
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1581,22 +1581,22 @@ CSS_PROP_TABLEBORDER(
     VARIANT_HK,
     kEmptyCellsKTable,
     CSS_PROP_NO_OFFSET,
     eStyleAnimType_None)
 CSS_PROP_POSITION(
     align-content,
     align_content,
     AlignContent,
-    CSS_PROPERTY_PARSE_VALUE,
-    "",
-    VARIANT_HK,
-    kAlignContentKTable,
-    offsetof(nsStylePosition, mAlignContent),
-    eStyleAnimType_EnumU8)
+    CSS_PROPERTY_PARSE_FUNCTION,
+    "",
+    0,
+    nullptr,
+    CSS_PROP_NO_OFFSET,
+    eStyleAnimType_None)
 CSS_PROP_POSITION(
     align-items,
     align_items,
     AlignItems,
     CSS_PROPERTY_PARSE_FUNCTION,
     "",
     0,
     nullptr,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1325,26 +1325,16 @@ const KTableValue nsCSSProps::kAlignCont
   eCSSKeyword_flex_start,    NS_STYLE_ALIGN_FLEX_START,
   eCSSKeyword_flex_end,      NS_STYLE_ALIGN_FLEX_END,
   eCSSKeyword_center,        NS_STYLE_ALIGN_CENTER,
   eCSSKeyword_left,          NS_STYLE_ALIGN_LEFT,
   eCSSKeyword_right,         NS_STYLE_ALIGN_RIGHT,
   eCSSKeyword_UNKNOWN,-1
 };
 
-const KTableValue nsCSSProps::kAlignContentKTable[] = {
-  eCSSKeyword_flex_start,    NS_STYLE_ALIGN_CONTENT_FLEX_START,
-  eCSSKeyword_flex_end,      NS_STYLE_ALIGN_CONTENT_FLEX_END,
-  eCSSKeyword_center,        NS_STYLE_ALIGN_CONTENT_CENTER,
-  eCSSKeyword_space_between, NS_STYLE_ALIGN_CONTENT_SPACE_BETWEEN,
-  eCSSKeyword_space_around,  NS_STYLE_ALIGN_CONTENT_SPACE_AROUND,
-  eCSSKeyword_stretch,       NS_STYLE_ALIGN_CONTENT_STRETCH,
-  eCSSKeyword_UNKNOWN,-1
-};
-
 const KTableValue nsCSSProps::kFlexDirectionKTable[] = {
   eCSSKeyword_row,            NS_STYLE_FLEX_DIRECTION_ROW,
   eCSSKeyword_row_reverse,    NS_STYLE_FLEX_DIRECTION_ROW_REVERSE,
   eCSSKeyword_column,         NS_STYLE_FLEX_DIRECTION_COLUMN,
   eCSSKeyword_column_reverse, NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE,
   eCSSKeyword_UNKNOWN,-1
 };
 
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -693,17 +693,16 @@ public:
   static const KTableValue kAlignOverflowPosition[]; // <overflow-position>
   static const KTableValue kAlignSelfPosition[];     // <self-position>
   static const KTableValue kAlignLegacy[];           // 'legacy'
   static const KTableValue kAlignLegacyPosition[];   // 'left/right/center'
   static const KTableValue kAlignAutoStretchBaseline[]; // 'auto/stretch/baseline/last-baseline'
   static const KTableValue kAlignAutoBaseline[]; // 'auto/baseline/last-baseline'
   static const KTableValue kAlignContentDistribution[]; // <content-distribution>
   static const KTableValue kAlignContentPosition[]; // <content-position>
-  static const KTableValue kAlignContentKTable[];
   static const KTableValue kAlignSelfKTable[];
   static const KTableValue kJustifyContentKTable[];
   // ------------------------------------------------------------------
   static const KTableValue kFlexDirectionKTable[];
   static const KTableValue kFlexWrapKTable[];
   static const KTableValue kFloatKTable[];
   static const KTableValue kFloatEdgeKTable[];
   static const KTableValue kFontKTable[];
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1317,16 +1317,17 @@ nsCSSValue::AppendToString(nsCSSProperty
       }
       nsStyleUtil::AppendBitmaskCSSValue(aProperty,
                                          intValue,
                                          NS_STYLE_CONTAIN_STRICT,
                                          NS_STYLE_CONTAIN_PAINT,
                                          aResult);
       break;
 
+    case eCSSProperty_align_content:
     case eCSSProperty_justify_content: {
       AppendAlignJustifyValueToString(intValue & NS_STYLE_ALIGN_ALL_BITS, aResult);
       auto fallback = intValue >> NS_STYLE_ALIGN_ALL_SHIFT;
       if (fallback) {
         MOZ_ASSERT(nsCSSProps::ValueToKeywordEnum(fallback & ~NS_STYLE_ALIGN_FLAG_BITS,
                                                   nsCSSProps::kAlignSelfPosition)
                    != eCSSKeyword_UNKNOWN, "unknown fallback value");
         aResult.Append(' ');
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -3856,26 +3856,16 @@ nsComputedDOMStyle::DoGetBorderImageRepe
   valueList->AppendCSSValue(valY);
   valY->SetIdent(
     nsCSSProps::ValueToKeywordEnum(border->mBorderImageRepeatV,
                                    nsCSSProps::kBorderImageRepeatKTable));
   return valueList;
 }
 
 CSSValue*
-nsComputedDOMStyle::DoGetAlignContent()
-{
-  nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
-  val->SetIdent(
-    nsCSSProps::ValueToKeywordEnum(StylePosition()->mAlignContent,
-                                   nsCSSProps::kAlignContentKTable));
-  return val;
-}
-
-CSSValue*
 nsComputedDOMStyle::DoGetFlexBasis()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
 
   // XXXdholbert We could make this more automagic and resolve percentages
   // if we wanted, by passing in a PercentageBaseGetter instead of nullptr
   // below.  Logic would go like this:
   //   if (i'm a flex item) {
@@ -3931,16 +3921,32 @@ CSSValue*
 nsComputedDOMStyle::DoGetOrder()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
   val->SetNumber(StylePosition()->mOrder);
   return val;
 }
 
 CSSValue*
+nsComputedDOMStyle::DoGetAlignContent()
+{
+  nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
+  nsAutoString str;
+  auto align = StylePosition()->ComputedAlignContent(StyleDisplay());
+  nsCSSValue::AppendAlignJustifyValueToString(align & NS_STYLE_ALIGN_ALL_BITS, str);
+  auto fallback = align >> NS_STYLE_ALIGN_ALL_SHIFT;
+  if (fallback) {
+    str.Append(' ');
+    nsCSSValue::AppendAlignJustifyValueToString(fallback, str);
+  }
+  val->SetString(str);
+  return val;
+}
+
+CSSValue*
 nsComputedDOMStyle::DoGetAlignItems()
 {
   nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
   nsAutoString str;
   auto align = StylePosition()->ComputedAlignItems(StyleDisplay());
   nsCSSValue::AppendAlignJustifyValueToString(align, str);
   val->SetString(str);
   return val;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -7790,21 +7790,32 @@ nsRuleNode::ComputePositionData(void* aS
   // box-sizing: enum, inherit, initial
   SetDiscrete(*aRuleData->ValueForBoxSizing(),
               pos->mBoxSizing, conditions,
               SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
               parentPos->mBoxSizing,
               NS_STYLE_BOX_SIZING_CONTENT, 0, 0, 0, 0);
 
   // align-content: enum, inherit, initial
-  SetDiscrete(*aRuleData->ValueForAlignContent(),
-              pos->mAlignContent, conditions,
-              SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
-              parentPos->mAlignContent,
-              NS_STYLE_ALIGN_CONTENT_STRETCH, 0, 0, 0, 0);
+  const auto& alignContentValue = *aRuleData->ValueForAlignContent();
+  if (MOZ_UNLIKELY(alignContentValue.GetUnit() == eCSSUnit_Inherit)) {
+    if (MOZ_LIKELY(parentContext)) {
+      pos->mAlignContent =
+        parentPos->ComputedAlignContent(parentContext->StyleDisplay());
+    } else {
+      pos->mAlignContent = NS_STYLE_ALIGN_AUTO;
+    }
+    conditions.SetUncacheable();
+  } else {
+    SetDiscrete(alignContentValue,
+                pos->mAlignContent, conditions,
+                SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL,
+                parentPos->mAlignContent, // unused, we handle 'inherit' above
+                NS_STYLE_ALIGN_AUTO, 0, 0, 0, 0);
+  }
 
   // align-items: enum, inherit, initial
   const auto& alignItemsValue = *aRuleData->ValueForAlignItems();
   if (MOZ_UNLIKELY(alignItemsValue.GetUnit() == eCSSUnit_Inherit)) {
     if (MOZ_LIKELY(parentContext)) {
       pos->mAlignItems =
         parentPos->ComputedAlignItems(parentContext->StyleDisplay());
     } else {
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -513,23 +513,24 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_JUSTIFY_SPACE_EVENLY     NS_STYLE_ALIGN_SPACE_EVENLY
 #define NS_STYLE_JUSTIFY_LEGACY           NS_STYLE_ALIGN_LEGACY
 #define NS_STYLE_JUSTIFY_SAFE             NS_STYLE_ALIGN_SAFE
 #define NS_STYLE_JUSTIFY_TRUE             NS_STYLE_ALIGN_TRUE
 #define NS_STYLE_JUSTIFY_FLAG_BITS        NS_STYLE_ALIGN_FLAG_BITS
 #define NS_STYLE_JUSTIFY_ALL_BITS         NS_STYLE_ALIGN_ALL_BITS
 #define NS_STYLE_JUSTIFY_ALL_SHIFT        NS_STYLE_ALIGN_ALL_SHIFT
 
-// See nsStylePosition
-#define NS_STYLE_ALIGN_CONTENT_FLEX_START       0
-#define NS_STYLE_ALIGN_CONTENT_FLEX_END         1
-#define NS_STYLE_ALIGN_CONTENT_CENTER           2
-#define NS_STYLE_ALIGN_CONTENT_SPACE_BETWEEN    3
-#define NS_STYLE_ALIGN_CONTENT_SPACE_AROUND     4
-#define NS_STYLE_ALIGN_CONTENT_STRETCH          5
+// XXX remove in a later patch after updating flexbox code with the new names
+#define NS_STYLE_ALIGN_CONTENT_AUTO            NS_STYLE_ALIGN_AUTO
+#define NS_STYLE_ALIGN_CONTENT_FLEX_START      NS_STYLE_ALIGN_FLEX_START
+#define NS_STYLE_ALIGN_CONTENT_FLEX_END        NS_STYLE_ALIGN_FLEX_END
+#define NS_STYLE_ALIGN_CONTENT_CENTER          NS_STYLE_ALIGN_CENTER
+#define NS_STYLE_ALIGN_CONTENT_STRETCH         NS_STYLE_ALIGN_STRETCH
+#define NS_STYLE_ALIGN_CONTENT_SPACE_BETWEEN   NS_STYLE_ALIGN_SPACE_BETWEEN
+#define NS_STYLE_ALIGN_CONTENT_SPACE_AROUND    NS_STYLE_ALIGN_SPACE_AROUND
 
 // XXX remove in a later patch after updating flexbox code with the new names
 #define NS_STYLE_ALIGN_ITEMS_FLEX_START         NS_STYLE_ALIGN_FLEX_START
 #define NS_STYLE_ALIGN_ITEMS_FLEX_END           NS_STYLE_ALIGN_FLEX_END
 #define NS_STYLE_ALIGN_ITEMS_CENTER             NS_STYLE_ALIGN_CENTER
 #define NS_STYLE_ALIGN_ITEMS_BASELINE           NS_STYLE_ALIGN_BASELINE
 #define NS_STYLE_ALIGN_ITEMS_STRETCH            NS_STYLE_ALIGN_STRETCH
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1426,17 +1426,17 @@ nsStylePosition::nsStylePosition(void)
   // which computes to 'minmax(auto, auto)'.
   mGridAutoColumnsMin.SetAutoValue();
   mGridAutoColumnsMax.SetAutoValue();
   mGridAutoRowsMin.SetAutoValue();
   mGridAutoRowsMax.SetAutoValue();
 
   mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
   mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
-  mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH;
+  mAlignContent = NS_STYLE_ALIGN_AUTO;
   mAlignItems = NS_STYLE_ALIGN_AUTO;
   mAlignSelf = NS_STYLE_ALIGN_AUTO;
   mJustifyContent = NS_STYLE_JUSTIFY_AUTO;
   mJustifyItems = NS_STYLE_JUSTIFY_AUTO;
   mJustifySelf = NS_STYLE_JUSTIFY_AUTO;
   mFlexDirection = NS_STYLE_FLEX_DIRECTION_ROW;
   mFlexWrap = NS_STYLE_FLEX_WRAP_NOWRAP;
   mObjectFit = NS_STYLE_OBJECT_FIT_FILL;
@@ -1691,16 +1691,26 @@ nsStylePosition::MapLeftRightToStart(uin
       if (aAxis == eLogicalAxisBlock) {
         return NS_STYLE_ALIGN_START | (aAlign & NS_STYLE_ALIGN_FLAG_BITS);
       }
     }
   }
   return aAlign;
 }
 
+uint16_t
+nsStylePosition::ComputedAlignContent(const nsStyleDisplay* aDisplay) const
+{
+  uint8_t val = mAlignContent & NS_STYLE_ALIGN_ALL_BITS;
+  val = MapLeftRightToStart(val, eLogicalAxisBlock, aDisplay);
+  uint8_t fallback = mAlignContent >> NS_STYLE_ALIGN_ALL_SHIFT;
+  fallback = MapLeftRightToStart(fallback, eLogicalAxisBlock, aDisplay);
+  return (uint16_t(fallback) << NS_STYLE_ALIGN_ALL_SHIFT) | uint16_t(val);
+}
+
 uint8_t
 nsStylePosition::ComputedAlignItems(const nsStyleDisplay* aDisplay) const
 {
   if (mAlignItems != NS_STYLE_ALIGN_AUTO) {
     return MapLeftRightToStart(mAlignItems, eLogicalAxisBlock, aDisplay);
   }
   return aDisplay->IsFlexOrGridDisplayType() ? NS_STYLE_ALIGN_STRETCH
                                              : NS_STYLE_ALIGN_START;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1392,16 +1392,22 @@ struct nsStylePosition {
     return nsChangeHint(0);
   }
 
   // XXXdholbert nsStyleBackground::Position should probably be moved to a
   // different scope, since we're now using it in multiple style structs.
   typedef nsStyleBackground::Position Position;
 
   /**
+   * Return the computed value for 'align-content' given our 'display' value in
+   * aDisplay.
+   */
+  uint16_t ComputedAlignContent(const nsStyleDisplay* aDisplay) const;
+
+  /**
    * Return the computed value for 'align-items' given our 'display' value in
    * aDisplay.
    */
   uint8_t ComputedAlignItems(const nsStyleDisplay* aDisplay) const;
 
   /**
    * Return the computed value for 'align-self' given our 'display' value in
    * aDisplay and the parent StyleContext aParent (or null for the root).
@@ -1439,23 +1445,23 @@ struct nsStylePosition {
   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, calc, none
   nsStyleCoord  mFlexBasis;             // [reset] coord, percent, enum, calc, auto
   nsStyleCoord  mGridAutoColumnsMin;    // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoColumnsMax;    // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoRowsMin;       // [reset] coord, percent, enum, calc, flex
   nsStyleCoord  mGridAutoRowsMax;       // [reset] coord, percent, enum, calc, flex
   uint8_t       mGridAutoFlow;          // [reset] enumerated. See nsStyleConsts.h
   uint8_t       mBoxSizing;             // [reset] see nsStyleConsts.h
-  uint8_t       mAlignContent;          // [reset] see nsStyleConsts.h
 private:
   friend class nsRuleNode;
   // Helper for the ComputedAlign/Justify* methods.
   uint8_t MapLeftRightToStart(uint8_t aAlign, mozilla::LogicalAxis aAxis,
                               const nsStyleDisplay* aDisplay) const;
 
+  uint16_t      mAlignContent;          // [reset] fallback value in the high byte
   uint8_t       mAlignItems;            // [reset] see nsStyleConsts.h
   uint8_t       mAlignSelf;             // [reset] see nsStyleConsts.h
   uint16_t      mJustifyContent;        // [reset] fallback value in the high byte
   uint8_t       mJustifyItems;          // [reset] see nsStyleConsts.h
   uint8_t       mJustifySelf;           // [reset] see nsStyleConsts.h
 public:
   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -4039,25 +4039,26 @@ var gCSSProperties = {
     initial_values: [ "no-drag" ],
     other_values: [ "drag" ],
     invalid_values: [ "none" ]
   },
   "align-content": {
     domProp: "alignContent",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
-    initial_values: [ "stretch" ],
-    other_values: [
-      "flex-start",
-      "flex-end",
-      "center",
-      "space-between",
-      "space-around"
-    ],
-    invalid_values: [ "abc", "30px", "0", "auto" ]
+    initial_values: [ "auto" ],
+    other_values: [ "start", "end", "flex-start", "flex-end", "center", "left",
+                    "right", "space-between", "space-around", "space-evenly",
+                    "baseline", "last-baseline", "stretch", "start safe",
+                    "true end", "true end stretch", "end safe space-evenly" ],
+    invalid_values: [ "none", "5", "self-end", "safe", "auto true", "true safe",
+                      "safe baseline", "baseline true", "baseline end", "end auto",
+                      "safe end true start", "safe end true", "auto safe start",
+                      "true end start", "end start safe", "space-between true",
+                      "stretch safe" ]
   },
   "align-items": {
     domProp: "alignItems",
     inherited: false,
     type: CSS_TYPE_LONGHAND,
     initial_values: [ "auto", "start" ],
     // Can't test 'left'/'right' here since that computes to 'start' for blocks.
     other_values: [ "end", "flex-start", "flex-end", "self-start", "self-end",