Bug 450652 – Style system changes to support CSS3 border-radius – parser changes (part 2) [r+sr=dbaron]
authorZack Weinberg <zweinberg@mozilla.com>
Wed, 01 Oct 2008 00:51:40 -0500
changeset 20040 5ada96f194859d24375016da8c98d895040a4a81
parent 20039 996f4f70b3d718c2a53915ecd70470c056242c06
child 20041 f50462bd2599ede3af527ddc6784504a2e799de3
push id2596
push userreed@reedloden.com
push dateWed, 01 Oct 2008 05:52:53 +0000
treeherdermozilla-central@d168111e0251 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs450652
milestone1.9.1b1pre
Bug 450652 – Style system changes to support CSS3 border-radius – parser changes (part 2) [r+sr=dbaron]
layout/style/nsCSSParser.cpp
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -4729,66 +4729,101 @@ CSSParserImpl::ParseDirectionalBoxProper
   AppendValue(subprops[1], typeVal);
   AppendValue(subprops[2], typeVal);
   return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseBoxCornerRadius(nsCSSProperty aPropID)
 {
-  nsCSSValue temp;
-  if (!ParsePositiveVariant(temp, VARIANT_HLP, nsnull))
+  nsCSSValue dimenX, dimenY;
+  // required first value
+  if (! ParsePositiveVariant(dimenX, VARIANT_HLP, nsnull))
     return PR_FALSE;
+  // optional second value (forbidden if first value is inherit/initial)
+  if (dimenX.GetUnit() == eCSSUnit_Inherit ||
+      dimenX.GetUnit() == eCSSUnit_Initial ||
+      ! ParsePositiveVariant(dimenY, VARIANT_LP, nsnull))
+    dimenY = dimenX;
+
   NS_ASSERTION(nsCSSProps::kTypeTable[aPropID] == eCSSType_ValuePair,
                nsPrintfCString(64, "type error (property='%s')",
                                nsCSSProps::GetStringValue(aPropID).get())
                .get());
   nsCSSValuePair& storage =
     *static_cast<nsCSSValuePair*>(mTempData.PropertyAt(aPropID));
-  storage.SetBothValuesTo(temp);
+  storage.mXValue = dimenX;
+  storage.mYValue = dimenY;
   mTempData.SetPropertyBit(aPropID);
   return PR_TRUE;
 }
 
 PRBool
 CSSParserImpl::ParseBoxCornerRadii(nsCSSCornerSizes& aRadii,
                                    const nsCSSProperty aPropIDs[])
 {
-  nsCSSRect temp;
-  PRInt32 count = 0;
+  // Rectangles are used as scratch storage.
+  // top => top-left, right => top-right,
+  // bottom => bottom-right, left => bottom-left.
+  nsCSSRect dimenX, dimenY;
+  PRInt32 countX = 0, countY = 0;
+
   NS_FOR_CSS_SIDES (side) {
-    if (! ParsePositiveVariant(temp.*nsCSSRect::sides[side], VARIANT_HLP,
-                               nsnull))
+    if (! ParsePositiveVariant(dimenX.*nsCSSRect::sides[side],
+                               side > 0 ? VARIANT_LP : VARIANT_HLP, nsnull))
       break;
-    count++;
-  }
-  if ((count == 0) || !ExpectEndProperty())
+    countX++;
+  }
+  if (countX == 0)
     return PR_FALSE;
 
-  if (count > 1) { // verify no more than single inherit or initial
+  if (ExpectSymbol('/', PR_TRUE)) {
     NS_FOR_CSS_SIDES (side) {
-      nsCSSUnit unit = (temp.*(nsCSSRect::sides[side])).GetUnit();
-      if (eCSSUnit_Inherit == unit || eCSSUnit_Initial == unit)
-        return PR_FALSE;
-    }
+      if (! ParsePositiveVariant(dimenY.*nsCSSRect::sides[side],
+                                 VARIANT_LP, nsnull))
+        break;
+      countY++;
+    }
+    if (countY == 0)
+      return PR_FALSE;
+  }
+  if (!ExpectEndProperty())
+    return PR_FALSE;
+
+  // if 'initial' or 'inherit' was used, it must be the only value
+  if (countX > 1 || countY > 0) {
+    nsCSSUnit unit = dimenX.mTop.GetUnit();
+    if (eCSSUnit_Inherit == unit || eCSSUnit_Initial == unit)
+      return PR_FALSE;
+  }
+
+  // if we have no Y-values, use the X-values
+  if (countY == 0) {
+    dimenY = dimenX;
+    countY = countX;
   }
 
   // Provide missing values by replicating some of the values found
-  switch (count) {
-    case 1: // Make right == top
-      temp.mRight = temp.mTop;
-    case 2: // Make bottom == top
-      temp.mBottom = temp.mTop;
-    case 3: // Make left == right
-      temp.mLeft = temp.mRight;
+  switch (countX) {
+    case 1: dimenX.mRight = dimenX.mTop;  // top-right same as top-left, and
+    case 2: dimenX.mBottom = dimenX.mTop; // bottom-right same as top-left, and 
+    case 3: dimenX.mLeft = dimenX.mRight; // bottom-left same as top-right
+  }
+
+  switch (countY) {
+    case 1: dimenY.mRight = dimenY.mTop;  // top-right same as top-left, and
+    case 2: dimenY.mBottom = dimenY.mTop; // bottom-right same as top-left, and 
+    case 3: dimenY.mLeft = dimenY.mRight; // bottom-left same as top-right
   }
 
   NS_FOR_CSS_SIDES(side) {
-    aRadii.GetFullCorner(NS_SIDE_TO_FULL_CORNER(side, PR_FALSE))
-      .SetBothValuesTo(temp.*nsCSSRect::sides[side]);
+    nsCSSValuePair& corner =
+      aRadii.GetFullCorner(NS_SIDE_TO_FULL_CORNER(side, PR_FALSE));
+    corner.mXValue = dimenX.*nsCSSRect::sides[side];
+    corner.mYValue = dimenY.*nsCSSRect::sides[side];
     mTempData.SetPropertyBit(aPropIDs[side]);
   }
   return PR_TRUE;
 }
 
 // These must be in CSS order (top,right,bottom,left) for indexing to work
 static const nsCSSProperty kBorderStyleIDs[] = {
   eCSSProperty_border_top_style,