Bug 446569 - Implement prefixed CSS3 columns shorthand r=dbaron
authorMichael Ventnor <mventnor@mozilla.com>
Tue, 23 Aug 2011 14:18:22 +1000
changeset 75699 ecb597abc0bfb40a3c42235c6cfcfc86af78616d
parent 75698 884897e976ad333070bc0a9668a670028ae69318
child 75702 a41b781330a6bf4669c6ec32f4082374924c2137
push id1413
push usermventnor@mozilla.com
push dateTue, 23 Aug 2011 04:22:43 +0000
treeherdermozilla-inbound@ecb597abc0bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs446569
milestone9.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 446569 - Implement prefixed CSS3 columns shorthand r=dbaron
dom/interfaces/css/nsIDOMCSS2Properties.idl
layout/style/Declaration.cpp
layout/style/nsCSSParser.cpp
layout/style/nsCSSPropList.h
layout/style/nsCSSProperty.h
layout/style/nsCSSProps.cpp
layout/style/test/property_database.js
--- a/dom/interfaces/css/nsIDOMCSS2Properties.idl
+++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl
@@ -46,17 +46,17 @@
  * The nsIDOMCSS2Properties interface is a datatype for additional
  * reflection of data already provided in nsIDOMCSSStyleDeclaration in
  * the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
-[builtinclass, scriptable, uuid(10f43750-b379-11e0-aff2-0800200c9a66)]
+[builtinclass, scriptable, uuid(286466f1-4246-4574-afdb-2f8a03ad7cc8)]
 interface nsIDOMCSS2Properties : nsISupports
 {
            attribute DOMString        background;
                                         // raises(DOMException) on setting
 
            attribute DOMString        backgroundAttachment;
                                         // raises(DOMException) on setting
 
@@ -652,16 +652,19 @@ interface nsIDOMCSS2Properties : nsISupp
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozStackSizing;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozBorderImage;
                                         // raises(DOMException) on setting
 
+           attribute DOMString        MozColumns;
+                                        // raises(DOMException) on setting
+
            attribute DOMString        MozColumnRule;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozColumnRuleWidth;
                                         // raises(DOMException) on setting
 
            attribute DOMString        MozColumnRuleStyle;
                                         // raises(DOMException) on setting
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -764,16 +764,25 @@ Declaration::GetValue(nsCSSProperty aPro
       const nsCSSValue &midValue =
         *data->ValueFor(eCSSProperty_marker_mid);
       const nsCSSValue &startValue =
         *data->ValueFor(eCSSProperty_marker_start);
       if (endValue == midValue && midValue == startValue)
         AppendValueToString(eCSSProperty_marker_end, aValue);
       break;
     }
+    case eCSSProperty__moz_columns: {
+      // Two values, column-count and column-width, separated by a space.
+      const nsCSSProperty* subprops =
+        nsCSSProps::SubpropertyEntryFor(aProperty);
+      AppendValueToString(subprops[0], aValue);
+      aValue.Append(PRUnichar(' '));
+      AppendValueToString(subprops[1], aValue);
+      break;
+    }
     default:
       NS_ABORT_IF_FALSE(false, "no other shorthands");
       break;
   }
 }
 
 PRBool
 Declaration::GetValueIsImportant(const nsAString& aProperty) const
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -487,16 +487,17 @@ protected:
   PRBool ParseCalcMultiplicativeExpression(nsCSSValue& aValue,
                                            PRInt32& aVariantMask,
                                            PRBool *aHadFinalWS);
   PRBool ParseCalcTerm(nsCSSValue& aValue, PRInt32& aVariantMask);
   PRBool RequireWhitespace();
 
   // for 'clip' and '-moz-image-region'
   PRBool ParseRect(nsCSSProperty aPropID);
+  PRBool ParseColumns();
   PRBool ParseContent();
   PRBool ParseCounterData(nsCSSProperty aPropID);
   PRBool ParseCursor();
   PRBool ParseFont();
   PRBool ParseFontWeight(nsCSSValue& aValue);
   PRBool ParseOneFamily(nsAString& aValue);
   PRBool ParseFamily(nsCSSValue& aValue);
   PRBool ParseFontSrc(nsCSSValue& aValue);
@@ -5487,16 +5488,18 @@ CSSParserImpl::ParsePropertyByFunction(n
     return ParseBoxCornerRadius(aPropID);
 
   case eCSSProperty_box_shadow:
   case eCSSProperty_text_shadow:
     return ParseShadowList(aPropID);
 
   case eCSSProperty_clip:
     return ParseRect(eCSSProperty_clip);
+  case eCSSProperty__moz_columns:
+    return ParseColumns();
   case eCSSProperty__moz_column_rule:
     return ParseBorderSide(kColumnRuleIDs, PR_FALSE);
   case eCSSProperty_content:
     return ParseContent();
   case eCSSProperty_counter_increment:
   case eCSSProperty_counter_reset:
     return ParseCounterData(aPropID);
   case eCSSProperty_cursor:
@@ -5582,16 +5585,20 @@ CSSParserImpl::ParsePropertyByFunction(n
 PRBool
 CSSParserImpl::ParseSingleValueProperty(nsCSSValue& aValue,
                                         nsCSSProperty aPropID)
 {
   if (aPropID == eCSSPropertyExtra_x_none_value) {
     return ParseVariant(aValue, VARIANT_NONE | VARIANT_INHERIT, nsnull);
   }
 
+  if (aPropID == eCSSPropertyExtra_x_auto_value) {
+    return ParseVariant(aValue, VARIANT_AUTO | VARIANT_INHERIT, nsnull);
+  }
+
   if (aPropID < 0 || aPropID >= eCSSProperty_COUNT_no_shorthands) {
     NS_ABORT_IF_FALSE(PR_FALSE, "not a single value property");
     return PR_FALSE;
   }
 
   if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_VALUE_PARSER_FUNCTION)) {
     switch (aPropID) {
       case eCSSProperty_font_family:
@@ -6841,16 +6848,58 @@ CSSParserImpl::ParseRect(nsCSSProperty a
     UngetToken();
     return PR_FALSE;
   }
 
   AppendValue(aPropID, val);
   return PR_TRUE;
 }
 
+PRBool
+CSSParserImpl::ParseColumns()
+{
+  // We use a similar "fake value" hack to ParseListStyle, because
+  // "auto" is acceptable for both column-count and column-width.
+  // If the fake "auto" value is found, and one of the real values isn't,
+  // that means the fake auto value is meant for the real value we didn't
+  // find.
+  static const nsCSSProperty columnIDs[] = {
+    eCSSPropertyExtra_x_auto_value,
+    eCSSProperty__moz_column_count,
+    eCSSProperty__moz_column_width
+  };
+  const PRInt32 numProps = NS_ARRAY_LENGTH(columnIDs);
+
+  nsCSSValue values[numProps];
+  PRInt32 found = ParseChoice(values, columnIDs, numProps);
+  if (found < 1 || !ExpectEndProperty()) {
+    return PR_FALSE;
+  }
+  if ((found & (1|2|4)) == (1|2|4) &&
+      values[0].GetUnit() ==  eCSSUnit_Auto) {
+    // We filled all 3 values, which is invalid
+    return PR_FALSE;
+  }
+
+  if ((found & 2) == 0) {
+    // Provide auto column-count
+    values[1].SetAutoValue();
+  }
+  if ((found & 4) == 0) {
+    // Provide auto column-width
+    values[2].SetAutoValue();
+  }
+
+  // Start at index 1 to skip the fake auto value.
+  for (PRInt32 index = 1; index < numProps; index++) {
+    AppendValue(columnIDs[index], values[index]);
+  }
+  return PR_TRUE;
+}
+
 #define VARIANT_CONTENT (VARIANT_STRING | VARIANT_URL | VARIANT_COUNTER | VARIANT_ATTR | \
                          VARIANT_KEYWORD)
 PRBool
 CSSParserImpl::ParseContent()
 {
   // We need to divide the 'content' keywords into two classes for
   // ParseVariant's sake, so we can't just use nsCSSProps::kContentKTable.
   static const PRInt32 kContentListKWs[] = {
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -1234,16 +1234,21 @@ CSS_PROP_COLOR(
     Color,
     CSS_PROPERTY_PARSE_VALUE |
         CSS_PROPERTY_APPLIES_TO_FIRST_LETTER_AND_FIRST_LINE |
         CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED,
     VARIANT_HC,
     nsnull,
     offsetof(nsStyleColor, mColor),
     eStyleAnimType_Color)
+CSS_PROP_SHORTHAND(
+    -moz-columns,
+    _moz_columns,
+    CSS_PROP_DOMPROP_PREFIXED(Columns),
+    CSS_PROPERTY_PARSE_FUNCTION)
 CSS_PROP_COLUMN(
     -moz-column-count,
     _moz_column_count,
     CSS_PROP_DOMPROP_PREFIXED(ColumnCount),
     CSS_PROPERTY_PARSE_VALUE |
         // Need to reject 0 in addition to negatives.  If we accept 0, we
         // need to change NS_STYLE_COLUMN_COUNT_AUTO to something else.
         CSS_PROPERTY_VALUE_AT_LEAST_ONE,
--- a/layout/style/nsCSSProperty.h
+++ b/layout/style/nsCSSProperty.h
@@ -71,17 +71,18 @@ enum nsCSSProperty {
   // with eCSSProperty_COUNT if we had a need for them to do so.
 
   // Extra values for use in the values of the 'transition-property'
   // property.
   eCSSPropertyExtra_no_properties,
   eCSSPropertyExtra_all_properties,
 
   // Extra dummy values for nsCSSParser internal use.
-  eCSSPropertyExtra_x_none_value
+  eCSSPropertyExtra_x_none_value,
+  eCSSPropertyExtra_x_auto_value
 };
 
 // The "descriptors" that can appear in a @font-face rule.
 // They have the syntax of properties but different value rules.
 // Keep in sync with kCSSRawFontDescs in nsCSSProps.cpp and
 // nsCSSFontFaceStyleDecl::Fields in nsCSSRules.cpp.
 enum nsCSSFontDesc {
   eCSSFontDesc_UNKNOWN = -1,
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -1963,16 +1963,22 @@ static const nsCSSProperty gOutlineSubpr
   // nsCSSDeclaration.cpp outputs the subproperties in this order.
   // It also depends on the color being third.
   eCSSProperty_outline_width,
   eCSSProperty_outline_style,
   eCSSProperty_outline_color,
   eCSSProperty_UNKNOWN
 };
 
+static const nsCSSProperty gColumnsSubpropTable[] = {
+  eCSSProperty__moz_column_count,
+  eCSSProperty__moz_column_width,
+  eCSSProperty_UNKNOWN
+};
+
 static const nsCSSProperty gColumnRuleSubpropTable[] = {
   // nsCSSDeclaration.cpp outputs the subproperties in this order.
   // It also depends on the color being third.
   eCSSProperty__moz_column_rule_width,
   eCSSProperty__moz_column_rule_style,
   eCSSProperty__moz_column_rule_color,
   eCSSProperty_UNKNOWN
 };
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -467,16 +467,26 @@ var gCSSProperties = {
 	"-moz-box-sizing": {
 		domProp: "MozBoxSizing",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "content-box" ],
 		other_values: [ "border-box", "padding-box" ],
 		invalid_values: [ "margin-box", "content", "padding", "border", "margin" ]
 	},
+	"-moz-columns": {
+		domProp: "MozColumns",
+		inherited: false,
+		type: CSS_TYPE_TRUE_SHORTHAND,
+		subproperties: [ "-moz-column-count", "-moz-column-width" ],
+		initial_values: [ "auto", "auto auto" ],
+		other_values: [ "3", "20px", "2 10px", "10px 2", "2 auto", "auto 2", "auto 50px", "50px auto" ],
+		invalid_values: [ "5%", "-1px", "-1", "3 5", "10px 4px", "10 2px 5in", "30px -1",
+		                  "auto 3 5px", "5 auto 20px", "auto auto auto" ]
+	},
 	"-moz-column-count": {
 		domProp: "MozColumnCount",
 		inherited: false,
 		type: CSS_TYPE_LONGHAND,
 		initial_values: [ "auto" ],
 		other_values: [ "1", "17" ],
 		// negative and zero invalid per editor's draft
 		invalid_values: [ "-1", "0", "3px" ]