Bug 752187 - Part 10: Implement rendering unprefixed gradients. r=dbaron
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Sat, 07 Jul 2012 10:27:08 -0400
changeset 98618 abebbd5a16bae2b62c60ca25ec6fd80e13d3639c
parent 98617 2f569b4103b6a0d0fe16e34f6e4ea38363108024
child 98619 f31675524ba3a0ba92e06489e78bdc9243c1033f
push id903
push usertim.taubert@gmx.de
push dateSun, 08 Jul 2012 11:40:07 +0000
treeherderfx-team@1751d97cc9e4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs752187
milestone16.0a1
Bug 752187 - Part 10: Implement rendering unprefixed gradients. r=dbaron
layout/base/nsCSSRendering.cpp
layout/base/nsStyleConsts.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1670,37 +1670,41 @@ ComputeLinearGradientLine(nsPresContext*
                           const gfxSize& aBoxSize,
                           gfxPoint* aLineStart,
                           gfxPoint* aLineEnd)
 {
   if (aGradient->mBgPosX.GetUnit() == eStyleUnit_None) {
     double angle;
     if (aGradient->mAngle.IsAngleValue()) {
       angle = aGradient->mAngle.GetAngleValueInRadians();
+      if (!aGradient->mLegacySyntax) {
+        angle = M_PI_2 - angle;
+      }
     } else {
       angle = -M_PI_2; // defaults to vertical gradient starting from top
     }
     gfxPoint center(aBoxSize.width/2, aBoxSize.height/2);
     *aLineEnd = ComputeGradientLineEndFromAngle(center, angle, aBoxSize);
     *aLineStart = gfxPoint(aBoxSize.width, aBoxSize.height) - *aLineEnd;
-  } else if (aGradient->mToCorner) {
+  } else if (!aGradient->mLegacySyntax) {
     float xSign = aGradient->mBgPosX.GetPercentValue() * 2 - 1;
     float ySign = 1 - aGradient->mBgPosY.GetPercentValue() * 2;
     double angle = atan2(ySign * aBoxSize.width, xSign * aBoxSize.height);
     gfxPoint center(aBoxSize.width/2, aBoxSize.height/2);
     *aLineEnd = ComputeGradientLineEndFromAngle(center, angle, aBoxSize);
     *aLineStart = gfxPoint(aBoxSize.width, aBoxSize.height) - *aLineEnd;
   } else {
     PRInt32 appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
     *aLineStart = gfxPoint(
       ConvertGradientValueToPixels(aGradient->mBgPosX, aBoxSize.width,
                                    appUnitsPerPixel),
       ConvertGradientValueToPixels(aGradient->mBgPosY, aBoxSize.height,
                                    appUnitsPerPixel));
     if (aGradient->mAngle.IsAngleValue()) {
+      MOZ_ASSERT(aGradient->mLegacySyntax);
       double angle = aGradient->mAngle.GetAngleValueInRadians();
       *aLineEnd = ComputeGradientLineEndFromAngle(*aLineStart, angle, aBoxSize);
     } else {
       // No angle, the line end is just the reflection of the start point
       // through the center of the box
       *aLineEnd = gfxPoint(aBoxSize.width, aBoxSize.height) - *aLineStart;
     }
   }
@@ -1772,16 +1776,24 @@ ComputeRadialGradientLine(nsPresContext*
       radiusX = radiusY = NS_hypot(offsetX, offsetY);
     } else {
       // maintain aspect ratio
       radiusX = offsetX*M_SQRT2;
       radiusY = offsetY*M_SQRT2;
     }
     break;
   }
+  case NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE: {
+    PRInt32 appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
+    radiusX = ConvertGradientValueToPixels(aGradient->mRadiusX,
+                                           aBoxSize.width, appUnitsPerPixel);
+    radiusY = ConvertGradientValueToPixels(aGradient->mRadiusY,
+                                           aBoxSize.height, appUnitsPerPixel);
+    break;
+  }
   default:
     NS_ABORT_IF_FALSE(false, "unknown radial gradient sizing method");
   }
   *aRadiusX = radiusX;
   *aRadiusY = radiusY;
 
   double angle;
   if (aGradient->mAngle.IsAngleValue()) {
--- a/layout/base/nsStyleConsts.h
+++ b/layout/base/nsStyleConsts.h
@@ -817,16 +817,17 @@ static inline mozilla::css::Side operato
 #define NS_STYLE_GRADIENT_SHAPE_LINEAR          0
 #define NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL      1
 #define NS_STYLE_GRADIENT_SHAPE_CIRCULAR        2
 
 #define NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE     0
 #define NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER   1
 #define NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE    2
 #define NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER  3
+#define NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE    4
 
 // See nsStyleSVG
 
 // dominant-baseline
 #define NS_STYLE_DOMINANT_BASELINE_AUTO              0
 #define NS_STYLE_DOMINANT_BASELINE_USE_SCRIPT        1
 #define NS_STYLE_DOMINANT_BASELINE_NO_CHANGE         2
 #define NS_STYLE_DOMINANT_BASELINE_RESET_SIZE        3
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1436,17 +1436,17 @@ nsComputedDOMStyle::GetCSSGradientString
     else
       aString.AssignLiteral("-moz-radial-gradient(");
   }
 
   bool needSep = false;
   nsAutoString tokenString;
   nsROCSSPrimitiveValue *tmpVal = GetROCSSPrimitiveValue();
 
-  if (aGradient->mToCorner) {
+  if (!aGradient->mLegacySyntax) {
     AppendCSSGradientToBoxPosition(aGradient, aString, needSep);
   } else {
     if (aGradient->mBgPosX.GetUnit() != eStyleUnit_None) {
       AppendCSSGradientLength(aGradient->mBgPosX, tmpVal, aString);
       needSep = true;
     }
     if (aGradient->mBgPosY.GetUnit() != eStyleUnit_None) {
       if (needSep) {
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -829,17 +829,31 @@ static void SetGradient(const nsCSSValue
                         nsStyleContext* aContext, nsStyleGradient& aResult,
                         bool& aCanStoreInRuleTree)
 {
   NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Gradient,
                     "The given data is not a gradient");
 
   const nsCSSValueGradient* gradient = aValue.GetGradientValue();
 
-  if (gradient->mIsRadial) {
+  if (gradient->mIsExplicitSize) {
+    SetCoord(gradient->GetRadiusX(), aResult.mRadiusX, nsStyleCoord(),
+             SETCOORD_LP | SETCOORD_STORE_CALC,
+             aContext, aPresContext, aCanStoreInRuleTree);
+    if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
+      SetCoord(gradient->GetRadiusY(), aResult.mRadiusY, nsStyleCoord(),
+               SETCOORD_LP | SETCOORD_STORE_CALC,
+               aContext, aPresContext, aCanStoreInRuleTree);
+      aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
+    } else {
+      aResult.mRadiusY = aResult.mRadiusX;
+      aResult.mShape = NS_STYLE_GRADIENT_SHAPE_CIRCULAR;
+    }
+    aResult.mSize = NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE;
+  } else if (gradient->mIsRadial) {
     if (gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated) {
       aResult.mShape = gradient->GetRadialShape().GetIntValue();
     } else {
       NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
                    "bad unit for radial shape");
       aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
     }
     if (gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated) {
@@ -851,19 +865,19 @@ static void SetGradient(const nsCSSValue
     }
   } else {
     NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
                  "bad unit for linear shape");
     NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None,
                  "bad unit for linear size");
     aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR;
     aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
-
-    aResult.mToCorner = !gradient->mIsLegacySyntax;
-  }
+  }
+
+  aResult.mLegacySyntax = gradient->mIsLegacySyntax;
 
   // bg-position
   SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext,
                    aResult.mBgPosX, aCanStoreInRuleTree);
 
   SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext,
                    aResult.mBgPosY, aCanStoreInRuleTree);
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1394,20 +1394,22 @@ nsStyleGradient::operator==(const nsStyl
                     "incorrect combination of shape and size");
   NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
                     aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
                     "incorrect combination of shape and size");
 
   if (mShape != aOther.mShape ||
       mSize != aOther.mSize ||
       mRepeating != aOther.mRepeating ||
-      mToCorner != aOther.mToCorner ||
+      mLegacySyntax != aOther.mLegacySyntax ||
       mBgPosX != aOther.mBgPosX ||
       mBgPosY != aOther.mBgPosY ||
-      mAngle != aOther.mAngle)
+      mAngle != aOther.mAngle ||
+      mRadiusX != aOther.mRadiusX ||
+      mRadiusY != aOther.mRadiusY)
     return false;
 
   if (mStops.Length() != aOther.mStops.Length())
     return false;
 
   for (PRUint32 i = 0; i < mStops.Length(); i++) {
     if (mStops[i].mLocation != aOther.mStops[i].mLocation ||
         mStops[i].mColor != aOther.mStops[i].mColor)
@@ -1416,17 +1418,17 @@ nsStyleGradient::operator==(const nsStyl
 
   return true;
 }
 
 nsStyleGradient::nsStyleGradient(void)
   : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
   , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
   , mRepeating(false)
-  , mToCorner(false)
+  , mLegacySyntax(false)
 {
 }
 
 bool
 nsStyleGradient::IsOpaque()
 {
   for (PRUint32 i = 0; i < mStops.Length(); i++) {
     if (NS_GET_A(mStops[i].mColor) < 255)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -122,22 +122,25 @@ struct nsStyleGradientStop {
 
 class nsStyleGradient {
 public:
   nsStyleGradient();
   PRUint8 mShape;  // NS_STYLE_GRADIENT_SHAPE_*
   PRUint8 mSize;   // NS_STYLE_GRADIENT_SIZE_*;
                    // not used (must be FARTHEST_CORNER) for linear shape
   bool mRepeating;
-  bool mToCorner;
+  bool mLegacySyntax;
 
   nsStyleCoord mBgPosX; // percent, coord, calc, none
   nsStyleCoord mBgPosY; // percent, coord, calc, none
   nsStyleCoord mAngle;  // none, angle
 
+  nsStyleCoord mRadiusX; // percent, coord, calc, none
+  nsStyleCoord mRadiusY; // percent, coord, calc, none
+
   // stops are in the order specified in the stylesheet
   nsTArray<nsStyleGradientStop> mStops;
 
   bool operator==(const nsStyleGradient& aOther) const;
   bool operator!=(const nsStyleGradient& aOther) const {
     return !(*this == aOther);
   };