Bug 513395: Implement revised CSS gradient notation (2/2): rendering
authorRobert O'Callahan <roc@ocallahan.org>, Ms2ger <ms2ger@gmail.com>
Mon, 02 Nov 2009 11:36:43 -0800
changeset 34476 32e1ceb06e441fa3d1d2aef530ae6eeb810036d6
parent 34475 c2261a741da8ed21fb5b114495b7a6d7f36231d0
child 34477 b884112e092282dd5546334bed5b6b313f4e0b22
push id10069
push userzweinberg@mozilla.com
push dateMon, 02 Nov 2009 19:39:33 +0000
treeherdermozilla-central@32e1ceb06e44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs513395
milestone1.9.3a1pre
Bug 513395: Implement revised CSS gradient notation (2/2): rendering
layout/base/nsCSSRendering.cpp
layout/base/nsCSSRendering.h
layout/base/tests/scrolling_helper.html
layout/reftests/css-gradients/linear-diagonal-1-ref.html
layout/reftests/css-gradients/linear-diagonal-1a.html
layout/reftests/css-gradients/linear-diagonal-1b.html
layout/reftests/css-gradients/linear-diagonal-2-ref.html
layout/reftests/css-gradients/linear-diagonal-2a.html
layout/reftests/css-gradients/linear-diagonal-2b.html
layout/reftests/css-gradients/linear-diagonal-3-ref.html
layout/reftests/css-gradients/linear-diagonal-3a.html
layout/reftests/css-gradients/linear-diagonal-3b.html
layout/reftests/css-gradients/linear-diagonal-4-ref.html
layout/reftests/css-gradients/linear-diagonal-4a.html
layout/reftests/css-gradients/linear-diagonal-4b.html
layout/reftests/css-gradients/linear-diagonal-5-ref.html
layout/reftests/css-gradients/linear-diagonal-5a.html
layout/reftests/css-gradients/linear-diagonal-6-ref.html
layout/reftests/css-gradients/linear-diagonal-6a.html
layout/reftests/css-gradients/linear-diagonal-7-ref.html
layout/reftests/css-gradients/linear-diagonal-7a.html
layout/reftests/css-gradients/linear-diagonal-8-ref.html
layout/reftests/css-gradients/linear-diagonal-8a.html
layout/reftests/css-gradients/linear-keywords-ref.html
layout/reftests/css-gradients/linear-keywords.html
layout/reftests/css-gradients/linear-mix-ref.html
layout/reftests/css-gradients/linear-mix.html
layout/reftests/css-gradients/linear-percent-ref.html
layout/reftests/css-gradients/linear-percent.html
layout/reftests/css-gradients/linear-position-1-ref.html
layout/reftests/css-gradients/linear-position-1a.html
layout/reftests/css-gradients/linear-ref.html
layout/reftests/css-gradients/linear-repeat-1-ref.html
layout/reftests/css-gradients/linear-repeat-1a.html
layout/reftests/css-gradients/linear-repeat-1b.html
layout/reftests/css-gradients/linear-repeat-1c.html
layout/reftests/css-gradients/linear-repeat-1d.html
layout/reftests/css-gradients/linear-repeat-1e.html
layout/reftests/css-gradients/linear-repeat-1f.html
layout/reftests/css-gradients/linear-repeat-1g.html
layout/reftests/css-gradients/linear-size-1-ref.html
layout/reftests/css-gradients/linear-size-1a.html
layout/reftests/css-gradients/linear-stops-1-ref.html
layout/reftests/css-gradients/linear-stops-1a.html
layout/reftests/css-gradients/linear-stops-1b.html
layout/reftests/css-gradients/linear-stops-1c.html
layout/reftests/css-gradients/linear-stops-1d.html
layout/reftests/css-gradients/linear-stops-1e.html
layout/reftests/css-gradients/linear-stops-1f.html
layout/reftests/css-gradients/linear-vertical-1-ref.html
layout/reftests/css-gradients/linear-vertical-1a.html
layout/reftests/css-gradients/linear-vertical-1b.html
layout/reftests/css-gradients/linear-vertical-1c.html
layout/reftests/css-gradients/linear-vertical-1d.html
layout/reftests/css-gradients/linear-viewport-ref.html
layout/reftests/css-gradients/linear-viewport.html
layout/reftests/css-gradients/linear-zero-length-1-ref.html
layout/reftests/css-gradients/linear-zero-length-1a.html
layout/reftests/css-gradients/linear-zero-length-1b.html
layout/reftests/css-gradients/linear-zero-length-1c.html
layout/reftests/css-gradients/linear.html
layout/reftests/css-gradients/nostops-ref.html
layout/reftests/css-gradients/nostops.html
layout/reftests/css-gradients/onestop-ref.html
layout/reftests/css-gradients/onestop.html
layout/reftests/css-gradients/radial-1-ref.html
layout/reftests/css-gradients/radial-1a.html
layout/reftests/css-gradients/radial-2-ref.html
layout/reftests/css-gradients/radial-2a.html
layout/reftests/css-gradients/radial-2b.html
layout/reftests/css-gradients/radial-position-1-ref.html
layout/reftests/css-gradients/radial-position-1a.html
layout/reftests/css-gradients/radial-ref.html
layout/reftests/css-gradients/radial-shape-closest-corner-1-ref.html
layout/reftests/css-gradients/radial-shape-closest-corner-1a.html
layout/reftests/css-gradients/radial-shape-closest-side-1-ref.html
layout/reftests/css-gradients/radial-shape-closest-side-1a.html
layout/reftests/css-gradients/radial-shape-farthest-corner-1-ref.html
layout/reftests/css-gradients/radial-shape-farthest-corner-1a.html
layout/reftests/css-gradients/radial-shape-farthest-side-1-ref.html
layout/reftests/css-gradients/radial-shape-farthest-side-1a.html
layout/reftests/css-gradients/radial-size-1-ref.html
layout/reftests/css-gradients/radial-size-1a.html
layout/reftests/css-gradients/radial-zero-length-1-ref.html
layout/reftests/css-gradients/radial-zero-length-1a.html
layout/reftests/css-gradients/radial-zero-length-1b.html
layout/reftests/css-gradients/radial-zero-length-1c.html
layout/reftests/css-gradients/radial-zero-length-1d.html
layout/reftests/css-gradients/radial-zero-length-1e.html
layout/reftests/css-gradients/radial-zero-length-1f.html
layout/reftests/css-gradients/radial.html
layout/reftests/css-gradients/reftest.list
layout/reftests/css-gradients/repeating-linear-1-ref.html
layout/reftests/css-gradients/repeating-linear-1a.html
layout/reftests/css-gradients/repeating-linear-1b.html
layout/reftests/css-gradients/repeating-linear-2-ref.html
layout/reftests/css-gradients/repeating-linear-2a.html
layout/reftests/css-gradients/repeating-radial-1-ref.html
layout/reftests/css-gradients/repeating-radial-1a.html
layout/reftests/css-gradients/repeating-radial-1b.html
layout/reftests/css-gradients/repeating-radial-2-ref.html
layout/reftests/css-gradients/repeating-radial-2a.html
layout/reftests/css-gradients/twostops-1-ref.html
layout/reftests/css-gradients/twostops-1a.html
layout/reftests/css-gradients/twostops-1b.html
layout/reftests/css-gradients/twostops-1c.html
layout/reftests/css-gradients/twostops-1d.html
layout/reftests/css-gradients/twostops-1e.html
layout/reftests/css-gradients/twostops-ref.html
layout/reftests/css-gradients/twostops.html
layout/style/nsStyleCoord.h
toolkit/themes/pinstripe/global/shared.inc
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -104,26 +104,24 @@ public:
   PRBool PrepareImage();
   /**
    * @return the image size in appunits. CSS gradient images don't have an
    * intrinsic size so we have to pass in a default that they will use.
    */
   nsSize ComputeSize(const nsSize& aDefault);
   /**
    * Draws the image to the target rendering context.
-   * @param aRepeat indicates whether the image is to be repeated (tiled)
    * @see nsLayoutUtils::DrawImage() for other parameters
    */
   void Draw(nsPresContext*       aPresContext,
             nsIRenderingContext& aRenderingContext,
             const nsRect&        aDest,
             const nsRect&        aFill,
             const nsPoint&       aAnchor,
-            const nsRect&        aDirty,
-            PRBool               aRepeat);
+            const nsRect&        aDirty);
 
 private:
   nsIFrame*                 mForFrame;
   nsStyleImage              mImage;
   nsStyleImageType          mType;
   nsCOMPtr<imgIContainer>   mImageContainer;
   nsRefPtr<nsStyleGradient> mGradientData;
   PRBool                    mIsReady;
@@ -1597,92 +1595,466 @@ nsCSSRendering::DetermineBackgroundColor
                                           aBackground,
                                           aFrame,
                                           drawBackgroundImage,
                                           drawBackgroundColor);
 }
 
 static gfxFloat
 ConvertGradientValueToPixels(const nsStyleCoord& aCoord,
-                             nscoord aFillLength,
-                             nscoord aAppUnitsPerPixel)
+                             gfxFloat aFillLength,
+                             PRInt32 aAppUnitsPerPixel)
 {
   switch (aCoord.GetUnit()) {
     case eStyleUnit_Percent:
-      return aCoord.GetPercentValue() * aFillLength / aAppUnitsPerPixel;
+      return aCoord.GetPercentValue() * aFillLength;
     case eStyleUnit_Coord:
-      return aCoord.GetCoordValue() / aAppUnitsPerPixel;
+      return NSAppUnitsToFloatPixels(aCoord.GetCoordValue(), aAppUnitsPerPixel);
     default:
       NS_WARNING("Unexpected coord unit");
       return 0;
   }
 }
 
+// Given a box with size aBoxSize and origin (0,0), and an angle aAngle,
+// and a starting point for the gradient line aStart, find the endpoint of
+// the gradient line --- the intersection of the gradient line with a line
+// perpendicular to aAngle that passes through the farthest corner in the
+// direction aAngle.
+static gfxPoint
+ComputeGradientLineEndFromAngle(const gfxPoint& aStart,
+                                double aAngle,
+                                const gfxSize& aBoxSize)
+{
+  double dx = cos(-aAngle);
+  double dy = sin(-aAngle);
+  gfxPoint farthestCorner(dx > 0 ? aBoxSize.width : 0,
+                          dy > 0 ? aBoxSize.height : 0);
+  gfxPoint delta = farthestCorner - aStart;
+  double u = delta.x*dy - delta.y*dx;
+  return farthestCorner + gfxPoint(-u*dy, u*dx);
+}
+
+// Compute the start and end points of the gradient line for a linear gradient.
+static void
+ComputeLinearGradientLine(nsPresContext* aPresContext,
+                          nsStyleGradient* aGradient,
+                          const gfxSize& aBoxSize,
+                          gfxPoint* aLineStart,
+                          gfxPoint* aLineEnd)
+{
+  if (aGradient->mBgPosX.GetUnit() == eStyleUnit_None) {
+    double angle;
+    if (aGradient->mAngle.IsAngleValue()) {
+      angle = aGradient->mAngle.GetAngleValueInRadians();
+    } 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 {
+    PRInt32 appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
+    *aLineStart = gfxPoint(
+      ConvertGradientValueToPixels(aGradient->mBgPosX, aBoxSize.width,
+                                   appUnitsPerPixel),
+      ConvertGradientValueToPixels(aGradient->mBgPosY, aBoxSize.height,
+                                   appUnitsPerPixel));
+    if (aGradient->mAngle.IsAngleValue()) {
+      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;
+    }
+  }
+}
+
+// Compute the start and end points of the gradient line for a radial gradient.
+// Also returns the horizontal and vertical radii defining the circle or
+// ellipse to use.
+static void
+ComputeRadialGradientLine(nsPresContext* aPresContext,
+                          nsStyleGradient* aGradient,
+                          const gfxSize& aBoxSize,
+                          gfxPoint* aLineStart,
+                          gfxPoint* aLineEnd,
+                          double* aRadiusX,
+                          double* aRadiusY)
+{
+  if (aGradient->mBgPosX.GetUnit() == eStyleUnit_None) {
+    // Default line start point is the center of the box
+    *aLineStart = gfxPoint(aBoxSize.width/2, aBoxSize.height/2);
+  } else {
+    PRInt32 appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
+    *aLineStart = gfxPoint(
+      ConvertGradientValueToPixels(aGradient->mBgPosX, aBoxSize.width,
+                                   appUnitsPerPixel),
+      ConvertGradientValueToPixels(aGradient->mBgPosY, aBoxSize.height,
+                                   appUnitsPerPixel));
+  }
+
+  // Compute gradient shape: the x and y radii of an ellipse.
+  double radiusX, radiusY;
+  double leftDistance = PR_ABS(aLineStart->x);
+  double rightDistance = PR_ABS(aBoxSize.width - aLineStart->x);
+  double topDistance = PR_ABS(aLineStart->y);
+  double bottomDistance = PR_ABS(aBoxSize.height - aLineStart->y);
+  switch (aGradient->mSize) {
+  case NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE:
+    radiusX = NS_MIN(leftDistance, rightDistance);
+    radiusY = NS_MIN(topDistance, bottomDistance);
+    if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
+      radiusX = radiusY = NS_MIN(radiusX, radiusY);
+    }
+    break;
+  case NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER: {
+    // Compute x and y distances to nearest corner
+    double offsetX = NS_MIN(leftDistance, rightDistance);
+    double offsetY = NS_MIN(topDistance, bottomDistance);
+    if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
+      radiusX = radiusY = NS_hypot(offsetX, offsetY);
+    } else {
+      // maintain aspect ratio
+      radiusX = offsetX*M_SQRT2;
+      radiusY = offsetY*M_SQRT2;
+    }
+    break;
+  }
+  case NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE:
+    radiusX = NS_MAX(leftDistance, rightDistance);
+    radiusY = NS_MAX(topDistance, bottomDistance);
+    if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
+      radiusX = radiusY = NS_MAX(radiusX, radiusY);
+    }
+    break;
+  case NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER: {
+    // Compute x and y distances to nearest corner
+    double offsetX = NS_MAX(leftDistance, rightDistance);
+    double offsetY = NS_MAX(topDistance, bottomDistance);
+    if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
+      radiusX = radiusY = NS_hypot(offsetX, offsetY);
+    } else {
+      // maintain aspect ratio
+      radiusX = offsetX*M_SQRT2;
+      radiusY = offsetY*M_SQRT2;
+    }
+    break;
+  }
+  default:
+    NS_ABORT_IF_FALSE(PR_FALSE, "unknown radial gradient sizing method");
+  }
+  *aRadiusX = radiusX;
+  *aRadiusY = radiusY;
+
+  double angle;
+  if (aGradient->mAngle.IsAngleValue()) {
+    angle = aGradient->mAngle.GetAngleValueInRadians();
+  } else {
+    // Default angle is 0deg
+    angle = 0.0;
+  }
+
+  // The gradient line end point is where the gradient line intersects
+  // the ellipse.
+  *aLineEnd = *aLineStart + gfxPoint(radiusX*cos(-angle), radiusY*sin(-angle));
+}
+
+// A resolved color stop --- with a specific position along the gradient line,
+// and a Thebes color
+struct ColorStop {
+  ColorStop(double aPosition, nscolor aColor) :
+    mPosition(aPosition), mColor(aColor) {}
+  double mPosition; // along the gradient line; 0=start, 1=end
+  gfxRGBA mColor;
+};
+
+// Returns aFrac*aC2 + (1 - aFrac)*C1. The interpolation is done
+// in unpremultiplied space, which is what SVG gradients and cairo
+// gradients expect.
+static gfxRGBA
+InterpolateColor(const gfxRGBA& aC1, const gfxRGBA& aC2, double aFrac)
+{
+  double other = 1 - aFrac;
+  return gfxRGBA(aC2.r*aFrac + aC1.r*other,
+                 aC2.g*aFrac + aC1.g*other,
+                 aC2.b*aFrac + aC1.b*other,
+                 aC2.a*aFrac + aC1.a*other);
+}
+
 void
 nsCSSRendering::PaintGradient(nsPresContext* aPresContext,
                               nsIRenderingContext& aRenderingContext,
                               nsStyleGradient* aGradient,
                               const nsRect& aDirtyRect,
                               const nsRect& aOneCellArea,
-                              const nsRect& aFillArea,
-                              PRBool aRepeat)
+                              const nsRect& aFillArea)
 {
-#if 0
+  if (aOneCellArea.IsEmpty())
+    return;
+
   gfxContext *ctx = aRenderingContext.ThebesContext();
   nscoord appUnitsPerPixel = aPresContext->AppUnitsPerDevPixel();
-
-  gfxRect dirtyRect = RectToGfxRect(aDirtyRect, appUnitsPerPixel);
-  gfxRect areaToFill = RectToGfxRect(aFillArea, appUnitsPerPixel);
   gfxRect oneCellArea = RectToGfxRect(aOneCellArea, appUnitsPerPixel);
-  gfxPoint fillOrigin = oneCellArea.TopLeft();
-
-  areaToFill = areaToFill.Intersect(dirtyRect);
-  if (areaToFill.IsEmpty())
-    return;
-
-  gfxFloat gradX0 = ConvertGradientValueToPixels(aGradient->mStartX,
-                        aOneCellArea.width, appUnitsPerPixel);
-  gfxFloat gradY0 = ConvertGradientValueToPixels(aGradient->mStartY,
-                        aOneCellArea.height, appUnitsPerPixel);
-  gfxFloat gradX1 = ConvertGradientValueToPixels(aGradient->mEndX,
-                        aOneCellArea.width, appUnitsPerPixel);
-  gfxFloat gradY1 = ConvertGradientValueToPixels(aGradient->mEndY,
-                        aOneCellArea.height, appUnitsPerPixel);
-
+
+  // Compute "gradient line" start and end relative to oneCellArea
+  gfxPoint lineStart, lineEnd;
+  double radiusX = 0, radiusY = 0; // for radial gradients only
+  if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
+    ComputeLinearGradientLine(aPresContext, aGradient, oneCellArea.size,
+                              &lineStart, &lineEnd);
+  } else {
+    ComputeRadialGradientLine(aPresContext, aGradient, oneCellArea.size,
+                              &lineStart, &lineEnd, &radiusX, &radiusY);
+  }
+  gfxFloat lineLength = NS_hypot(lineEnd.x - lineStart.x,
+                                 lineEnd.y - lineStart.y);
+
+  NS_ABORT_IF_FALSE(aGradient->mStops.Length() >= 2,
+                    "The parser should reject gradients with less than two stops");
+
+  // Build color stop array and compute stop positions
+  nsTArray<ColorStop> stops;
+  // If there is a run of stops before stop i that did not have specified
+  // positions, then this is the index of the first stop in that run, otherwise
+  // it's -1.
+  PRInt32 firstUnsetPosition = -1;
+  for (PRUint32 i = 0; i < aGradient->mStops.Length(); ++i) {
+    const nsStyleGradientStop& stop = aGradient->mStops[i];
+    double position;
+    switch (stop.mLocation.GetUnit()) {
+    case eStyleUnit_None:
+      if (i == 0) {
+        // First stop defaults to position 0.0
+        position = 0.0;
+      } else if (i == aGradient->mStops.Length() - 1) {
+        // Last stop defaults to position 1.0
+        position = 1.0;
+      } else {
+        // Other stops with no specified position get their position assigned
+        // later by interpolation, see below.
+        // Remeber where the run of stops with no specified position starts,
+        // if it starts here.
+        if (firstUnsetPosition < 0) {
+          firstUnsetPosition = i;
+        }
+        stops.AppendElement(ColorStop(0, stop.mColor));
+        continue;
+      }
+      break;
+    case eStyleUnit_Percent:
+      position = stop.mLocation.GetPercentValue();
+      break;
+    case eStyleUnit_Coord:
+      position = lineLength < 1e-6 ? 0.0 :
+          stop.mLocation.GetCoordValue() / appUnitsPerPixel / lineLength;
+      break;
+    default:
+      NS_ABORT_IF_FALSE(PR_FALSE, "Unknown stop position type");
+    }
+
+    if (i > 0) {
+      // Prevent decreasing stop positions by advancing this position
+      // to the previous stop position, if necessary
+      position = NS_MAX(position, stops[i - 1].mPosition);
+    }
+    stops.AppendElement(ColorStop(position, stop.mColor));
+    if (firstUnsetPosition > 0) {
+      // Interpolate positions for all stops that didn't have a specified position
+      double p = stops[firstUnsetPosition - 1].mPosition;
+      double d = (stops[i].mPosition - p)/(i - firstUnsetPosition + 1);
+      for (PRUint32 j = firstUnsetPosition; j < i; ++j) {
+        p += d;
+        stops[j].mPosition = p;
+      }
+      firstUnsetPosition = -1;
+    }
+  }
+
+  // Eliminate negative-position stops if the gradient is radial.
+  double firstStop = stops[0].mPosition;
+  if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR && firstStop < 0.0) {
+    if (aGradient->mRepeating) {
+      // Choose an instance of the repeated pattern that gives us all positive
+      // stop-offsets.
+      double lastStop = stops[stops.Length() - 1].mPosition;
+      double stopDelta = lastStop - firstStop;
+      // If all the stops are in approximately the same place then logic below
+      // will kick in that makes us draw just the last stop color, so don't
+      // try to do anything in that case. We certainly need to avoid
+      // dividing by zero.
+      if (stopDelta >= 1e-6) {
+        double instanceCount = NS_ceil(-firstStop/stopDelta);
+        // Advance stops by instanceCount multiples of the period of the
+        // repeating gradient.
+        double offset = instanceCount*stopDelta;
+        for (PRUint32 i = 0; i < stops.Length(); i++) {
+          stops[i].mPosition += offset;
+        }
+      }
+    } else {
+      // Move negative-position stops to position 0.0. We may also need
+      // to set the color of the stop to the color the gradient should have
+      // at the center of the ellipse.
+      for (PRUint32 i = 0; i < stops.Length(); i++) {
+        double pos = stops[i].mPosition;
+        if (pos < 0.0) {
+          stops[i].mPosition = 0.0;
+          // If this is the last stop, we don't need to adjust the color,
+          // it will fill the entire area.
+          if (i < stops.Length() - 1) {
+            double nextPos = stops[i + 1].mPosition;
+            // If nextPos is approximately equal to pos, then we don't
+            // need to adjust the color of this stop because it's
+            // not going to be displayed.
+            // If nextPos is negative, we don't need to adjust the color of
+            // this stop since it's not going to be displayed because
+            // nextPos will also be moved to 0.0.
+            if (nextPos >= 0.0 && nextPos - pos >= 1e-6) {
+              // Compute how far the new position 0.0 is along the interval
+              // between pos and nextPos.
+              // XXX Color interpolation (in cairo, too) should use the
+              // CSS 'color-interpolation' property!
+              double frac = (0.0 - pos)/(nextPos - pos);
+              stops[i].mColor =
+                InterpolateColor(stops[i].mColor, stops[i + 1].mColor, frac);
+            }
+          }
+        }
+      }
+    }
+    firstStop = stops[0].mPosition;
+    NS_ABORT_IF_FALSE(firstStop >= 0.0, "Failed to fix stop offsets");
+  }
+
+  double lastStop = stops[stops.Length() - 1].mPosition;
+  // Cairo gradients must have stop positions in the range [0, 1]. So,
+  // stop positions will be normalized below by subtracting firstStop and then
+  // multiplying by stopScale.
+  double stopScale;
+  double stopDelta = lastStop - firstStop;
+  if (stopDelta < 1e-6 || lineLength < 1e-6 ||
+      (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR &&
+       (radiusX < 1e-6 || radiusY < 1e-6))) {
+    // Stops are all at the same place. Map all stops to 0.0.
+    // For radial gradients we need to fill with the last stop color,
+    // so just set both radii to 0.
+    stopScale = 0.0;
+    radiusX = radiusY = 0.0;
+    lastStop = firstStop;
+  } else {
+    stopScale = 1.0/stopDelta;
+  }
+
+  // Create the gradient pattern.
   nsRefPtr<gfxPattern> gradientPattern;
-  if (aGradient->mIsRadial) {
-    gfxFloat gradRadius0 = double(aGradient->mStartRadius) / appUnitsPerPixel;
-    gfxFloat gradRadius1 = double(aGradient->mEndRadius) / appUnitsPerPixel;
-    gradientPattern = new gfxPattern(gradX0, gradY0, gradRadius0,
-                                     gradX1, gradY1, gradRadius1);
+  if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
+    // Compute the actual gradient line ends we need to pass to cairo after
+    // stops have been normalized.
+    gfxPoint gradientStart = lineStart + (lineEnd - lineStart)*firstStop;
+    gfxPoint gradientEnd = lineStart + (lineEnd - lineStart)*lastStop;
+
+    if (stopScale == 0.0) {
+      // Stops are all at the same place. For repeating gradients, this will
+      // just paint the last stop color. We don't need to do anything.
+      // For non-repeating gradients, this should render as two colors, one
+      // on each "side" of the gradient line segment, which is a point. All
+      // our stops will be at 0.0; we just need to set the direction vector
+      // correctly.
+      gradientEnd = gradientStart + (lineEnd - lineStart);
+    }
+
+    gradientPattern = new gfxPattern(gradientStart.x, gradientStart.y,
+                                     gradientEnd.x, gradientEnd.y);
   } else {
-    gradientPattern = new gfxPattern(gradX0, gradY0, gradX1, gradY1);
+    NS_ASSERTION(firstStop >= 0.0,
+                 "Negative stops not allowed for radial gradients");
+
+    // To form an ellipse, we'll stretch a circle vertically, if necessary.
+    // So our radii are based on radiusX.
+    double innerRadius = radiusX*firstStop;
+    double outerRadius = radiusX*lastStop;
+    gradientPattern = new gfxPattern(lineStart.x, lineStart.y, innerRadius,
+                                     lineStart.x, lineStart.y, outerRadius);
+    if (gradientPattern && radiusX != radiusY) {
+      // Stretch the circles into ellipses vertically by setting a transform
+      // in the pattern.
+      // Recall that this is the transform from user space to pattern space.
+      // So to stretch the ellipse by factor of P vertically, we scale
+      // user coordinates by 1/P.
+      gfxMatrix matrix;
+      matrix.Translate(lineStart);
+      matrix.Scale(1.0, radiusX/radiusY);
+      matrix.Translate(-lineStart);
+      gradientPattern->SetMatrix(matrix);
+    }
   }
-
   if (!gradientPattern || gradientPattern->CairoStatus())
     return;
 
-  for (PRUint32 i = 0; i < aGradient->mStops.Length(); i++) {
-    gradientPattern->AddColorStop(aGradient->mStops[i].mPosition,
-                                  gfxRGBA(aGradient->mStops[i].mColor));
+  // Now set normalized color stops in pattern.
+  if (stopScale == 0.0) {
+    // Non-repeating linear gradient with all stops in same place -> just add
+    // first stop and last stop, both at position 0.
+    // Repeating or radial gradient with all stops in the same place -> just
+    // paint the last stop color.
+    if (!aGradient->mRepeating &&
+        aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_LINEAR) {
+      gradientPattern->AddColorStop(0.0, stops[0].mColor);
+    }
+    gradientPattern->AddColorStop(0.0, stops[stops.Length() - 1].mColor);
+  } else {
+    // Use all stops
+    for (PRUint32 i = 0; i < stops.Length(); i++) {
+      double pos = stopScale*(stops[i].mPosition - firstStop);
+      gradientPattern->AddColorStop(pos, stops[i].mColor);
+    }
   }
 
-  if (aRepeat)
+  // Set repeat mode. Default cairo extend mode is PAD.
+  if (aGradient->mRepeating) {
     gradientPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
-
-  ctx->Save();
-  ctx->NewPath();
-  // The fill origin is part of the translate call so the pattern starts at
-  // the desired point, rather than (0,0).
-  ctx->Translate(fillOrigin);
-  ctx->SetPattern(gradientPattern);
-  ctx->Rectangle(areaToFill - fillOrigin, PR_TRUE);
-  ctx->Fill();
-  ctx->Restore();
-#endif
+  }
+
+  // Paint gradient tiles. This isn't terribly efficient, but doing it this
+  // way is simple and sure to get pixel-snapping right. We could speed things
+  // up by drawing tiles into temporary surfaces and copying those to the
+  // destination, but after pixel-snapping tiles may not all be the same size.
+  nsRect dirty;
+  dirty.IntersectRect(aDirtyRect, aFillArea);
+  gfxRect areaToFill = RectToGfxRect(aFillArea, appUnitsPerPixel);
+  gfxMatrix ctm = ctx->CurrentMatrix();
+
+  // Compute which tile is the top-left tile to be drawn.
+  PRInt32 firstTileX = (dirty.x - aOneCellArea.x)/aOneCellArea.width;
+  PRInt32 firstTileY = (dirty.y - aOneCellArea.y)/aOneCellArea.height;
+  // xStart/yStart are the top-left corner of the top-left tile.
+  nscoord xStart = firstTileX*aOneCellArea.width + aOneCellArea.x;
+  nscoord yStart = firstTileY*aOneCellArea.height + aOneCellArea.y;
+  nscoord xEnd = dirty.XMost();
+  nscoord yEnd = dirty.YMost();
+  // x and y are the top-left corner of the tile to draw
+  for (nscoord y = yStart; y < yEnd; y += aOneCellArea.height) {
+    for (nscoord x = xStart; x < xEnd; x += aOneCellArea.width) {
+      // The coordinates of the tile
+      gfxRect tileRect =
+        RectToGfxRect(nsRect(x, y, aOneCellArea.width, aOneCellArea.height),
+                      appUnitsPerPixel);
+      // The actual area to fill with this tile is the intersection of this
+      // tile with the overall area we're supposed to be filling
+      gfxRect fillRect = tileRect.Intersect(areaToFill);
+      ctx->NewPath();
+      ctx->Translate(tileRect.pos);
+      ctx->SetPattern(gradientPattern);
+      ctx->Rectangle(fillRect - tileRect.pos, PR_TRUE);
+      ctx->Fill();
+      ctx->SetMatrix(ctm);
+    }
+  }
 }
 
 void
 nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
                                       nsIRenderingContext& aRenderingContext,
                                       nsIFrame* aForFrame,
                                       const nsRect& aDirtyRect,
                                       const nsRect& aBorderArea,
@@ -2099,18 +2471,17 @@ PaintBackgroundLayer(nsPresContext* aPre
   }
   if (repeat & NS_STYLE_BG_REPEAT_Y) {
     fillArea.y = aBGClipRect.y;
     fillArea.height = aBGClipRect.height;
   }
   fillArea.IntersectRect(fillArea, aBGClipRect);
 
   imageRenderer.Draw(aPresContext, aRenderingContext, destArea, fillArea,
-                     anchor + aBorderArea.TopLeft(), aDirtyRect,
-                     (repeat != NS_STYLE_BG_REPEAT_OFF));
+                     anchor + aBorderArea.TopLeft(), aDirtyRect);
 }
 
 static void
 DrawBorderImage(nsPresContext*       aPresContext,
                 nsIRenderingContext& aRenderingContext,
                 nsIFrame*            aForFrame,
                 const nsRect&        aBorderArea,
                 const nsStyleBorder& aBorderStyle,
@@ -3220,18 +3591,17 @@ ImageRenderer::ComputeSize(const nsSize&
 }
 
 void
 ImageRenderer::Draw(nsPresContext*       aPresContext,
                          nsIRenderingContext& aRenderingContext,
                          const nsRect&        aDest,
                          const nsRect&        aFill,
                          const nsPoint&       aAnchor,
-                         const nsRect&        aDirty,
-                         PRBool               aRepeat)
+                         const nsRect&        aDirty)
 {
   if (!mIsReady) {
     NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
     return;
   }
 
   if (aDest.IsEmpty() || aFill.IsEmpty())
     return;
@@ -3244,17 +3614,17 @@ ImageRenderer::Draw(nsPresContext*      
                              : (PRUint32) imgIContainer::FLAG_NONE;
       nsLayoutUtils::DrawImage(&aRenderingContext, mImageContainer,
           nsLayoutUtils::GetGraphicsFilterForFrame(mForFrame),
           aDest, aFill, aAnchor, aDirty, drawFlags);
       break;
     }
     case eStyleImageType_Gradient:
       nsCSSRendering::PaintGradient(aPresContext, aRenderingContext,
-          mGradientData, aDirty, aDest, aFill, aRepeat);
+          mGradientData, aDirty, aDest, aFill);
       break;
     case eStyleImageType_Null:
     default:
       break;
   }
 }
 
 // -----
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -130,18 +130,17 @@ struct nsCSSRendering {
   /**
    * Render a gradient for an element.
    */
   static void PaintGradient(nsPresContext* aPresContext,
                             nsIRenderingContext& aRenderingContext,
                             nsStyleGradient* aGradient,
                             const nsRect& aDirtyRect,
                             const nsRect& aOneCellArea,
-                            const nsRect& aFillArea,
-                            PRBool aRepeat);
+                            const nsRect& aFillArea);
 
   /**
    * Gets the root frame for the frame
    */
   static nsIFrame* FindRootFrame(nsIFrame* aForFrame);
 
   /**
    * @return PR_TRUE if |aFrame| is a canvas frame, in the CSS sense.
--- a/layout/base/tests/scrolling_helper.html
+++ b/layout/base/tests/scrolling_helper.html
@@ -20,22 +20,22 @@ body > div {
      tests which expect to observe scrolling happening. -->
 
 <!-- Each of the DIV children of the BODY is one test. We scroll that DIV's
      scrollTop (or scrollLeft, if the DIV's class is 'horizontal')
      from 0 to 20 and then call the function given by the DIV's id,
      passing the blit region and the paint region as a parameters. -->
 
 <div id="testSimpleScroll">
-  <div style="height:300px; background:-moz-linear-gradient(top, bottom, from(red), to(black));"></div>
+  <div style="height:300px; background:-moz-linear-gradient(top, red, black);"></div>
 </div>
 
 <div id="testFixedBackground">
-  <div style="height:300px; margin-bottom:-300px; background:-moz-linear-gradient(left, right, from(red), to(black)) fixed;"></div>
-  <div style="height:300px; background:-moz-linear-gradient(top, bottom, from(rgba(0,0,0,0.7)), to(rgba(255,0,0,0.7)));"></div>
+  <div style="height:300px; margin-bottom:-300px; background:-moz-linear-gradient(left, red, black) fixed;"></div>
+  <div style="height:300px; background:-moz-linear-gradient(top, rgba(0,0,0,0.7), rgba(255,0,0,0.7));"></div>
 </div>
 
 <div id="testFixedPosOverlay">
   <div style="position:fixed; left:0; top:50px; width:100px; height:45px; background:yellow;"></div>
   <p>Hello
   <p>Hello
   <p>Hello
   <p>Hello
@@ -55,41 +55,41 @@ body > div {
   <p>Hello
   <p>Hello
   <p>Hello
   <p>Hello
   <p>Hello
 </div>
 
 <div style="border:1px solid black;" id="testBorder">
-  <div style="height:300px; background:-moz-linear-gradient(top, bottom, from(red), to(black));"></div>
+  <div style="height:300px; background:-moz-linear-gradient(top, red, black);"></div>
 </div>
 
 <div id="testScrollOutOfView">
-  <div style="height:10px; margin-bottom:210px; background:-moz-linear-gradient(top, bottom, from(rgba(0,0,0,0.7)), to(rgba(255,0,0,0.7)));"></div>
+  <div style="height:10px; margin-bottom:210px; background:-moz-linear-gradient(top, rgba(0,0,0,0.7), rgba(255,0,0,0.7));"></div>
 </div>
 
 <div id="testScrollIntoView">
-  <div style="height:10px; margin-top:210px; background:-moz-linear-gradient(top, bottom, from(rgba(0,0,0,0.7)), to(rgba(255,0,0,0.7)));"></div>
+  <div style="height:10px; margin-top:210px; background:-moz-linear-gradient(top, rgba(0,0,0,0.7), rgba(255,0,0,0.7));"></div>
 </div>
 
 <div id="testSimpleScrollWithSubpixelOffset1" style="top:0.2px">
-  <div style="height:300px; background:-moz-linear-gradient(top, bottom, from(red), to(black));"></div>
+  <div style="height:300px; background:-moz-linear-gradient(top, red, black);"></div>
 </div>
 
 <div id="testSimpleScrollWithSubpixelOffset2" style="top:0.8px">
-  <div style="height:300px; background:-moz-linear-gradient(top, bottom, from(red), to(black));"></div>
+  <div style="height:300px; background:-moz-linear-gradient(top, red, black);"></div>
 </div>
 
 <div id="testSimpleScrollWithSubpixelOffset3" style="left:0.2px" class="horizontal">
-  <div style="width:300px; height:200px; background:-moz-linear-gradient(left, right, from(red), to(black));"></div>
+  <div style="width:300px; height:200px; background:-moz-linear-gradient(left, red, black);"></div>
 </div>
 
 <div id="testSimpleScrollWithSubpixelOffset4" style="left:0.8px" class="horizontal">
-  <div style="width:300px; height:200px; background:-moz-linear-gradient(left, right, from(red), to(black));"></div>
+  <div style="width:300px; height:200px; background:-moz-linear-gradient(left, red, black);"></div>
 </div>
 
 <div id="testMovingClipArea">
   <div style="margin-top:20px; height:20px; margin-bottom:300px; background-color:blue; overflow:hidden;"></div>
 </div>
 
 <script>
 var tests = document.querySelectorAll("body>div");
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-1-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top left, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-1a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top left -45deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-1b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(-45deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-2-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top right, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-2a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top right -135deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-2b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(-135deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-3-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom right, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-3a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom right 135deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-3b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(135deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-4-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom left, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-4a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom left 45deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-4b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(45deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-5-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom right 135deg, white 75%, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-5a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(100px 100px 135deg, white, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-6-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom left 45deg, white 75%, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-6a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(300px 100px 45deg, white, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-7-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top left -45deg, white 75%, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-7a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(300px 300px -45deg, white, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-8-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top right -135deg, white 75%, black); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-diagonal-8a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(100px 300px -135deg, white, black); width: 400px; height: 400px;"></div>
--- a/layout/reftests/css-gradients/linear-keywords-ref.html
+++ b/layout/reftests/css-gradients/linear-keywords-ref.html
@@ -1,16 +1,16 @@
 <html xmlns="http://www.w3.org/1999/xhtml" 
       class="reftest-wait">
 <head>
 <script>
 function doDraw() {
   var ctx = document.getElementById('canvas').getContext('2d');
 
-  var grad = ctx.createLinearGradient(0,0,150,300);
+  var grad = ctx.createLinearGradient(0,0,300,300);
   grad.addColorStop(0, '#0000ff');
   grad.addColorStop(1, '#000000');
 
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,300,300);
 
   document.documentElement.removeAttribute('class');
 }
--- a/layout/reftests/css-gradients/linear-keywords.html
+++ b/layout/reftests/css-gradients/linear-keywords.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(left top, center bottom, from(#0000ff), to(#000000)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(left top, #0000ff, #000000) no-repeat; width: 300px; height: 300px;"><br></div>
--- a/layout/reftests/css-gradients/linear-mix-ref.html
+++ b/layout/reftests/css-gradients/linear-mix-ref.html
@@ -1,25 +1,25 @@
 <html xmlns="http://www.w3.org/1999/xhtml" 
       class="reftest-wait">
 <head>
 <script>
 function doDraw() {
   var ctx = document.getElementById('canvas').getContext('2d');
 
-  var grad = ctx.createLinearGradient(150,20,270,130);
+  var grad = ctx.createLinearGradient(120,20,300,20);
   grad.addColorStop(0, '#0000ff');
   grad.addColorStop(1, '#000000');
 
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,300,300);
 
   ctx = document.getElementById('canvas2').getContext('2d');
 
-  grad = ctx.createLinearGradient(30,300,300,50);
+  grad = ctx.createLinearGradient(30,300,30,0);
   grad.addColorStop(0, '#00ff00');
   grad.addColorStop(1, '#000000');
 
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,300,300);
 
   document.documentElement.removeAttribute('class');
 }
--- a/layout/reftests/css-gradients/linear-mix.html
+++ b/layout/reftests/css-gradients/linear-mix.html
@@ -1,3 +1,3 @@
-<div style="background: -moz-linear-gradient(center 20px, 90% 130px, from(#0000ff), to(#000000)) no-repeat; width: 300px; height: 300px; position: absolute; top: 30px; left: 30px;"><br></div>
+<div style="background: -moz-linear-gradient(40% 20px 0deg, #0000ff, #000000) no-repeat; width: 300px; height: 300px; position: absolute; top: 30px; left: 30px;"><br></div>
 
-<div style="background: -moz-linear-gradient(10% bottom, right 50px, from(#00ff00), to(#000000)) no-repeat; width: 300px; height: 300px; position: absolute; top: 360px; left: 30px;"><br></div>
+<div style="background: -moz-linear-gradient(10% bottom 90deg, #00ff00, #000000) no-repeat; width: 300px; height: 300px; position: absolute; top: 360px; left: 30px;"><br></div>
--- a/layout/reftests/css-gradients/linear-percent-ref.html
+++ b/layout/reftests/css-gradients/linear-percent-ref.html
@@ -1,16 +1,16 @@
 <html xmlns="http://www.w3.org/1999/xhtml" 
       class="reftest-wait">
 <head>
 <script>
 function doDraw() {
   var ctx = document.getElementById('canvas').getContext('2d');
 
-  var grad = ctx.createLinearGradient(30,60,240,270);
+  var grad = ctx.createLinearGradient(30,60,300,60);
   grad.addColorStop(0, '#0000ff');
   grad.addColorStop(1, '#000000');
 
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,300,300);
 
   document.documentElement.removeAttribute('class');
 }
--- a/layout/reftests/css-gradients/linear-percent.html
+++ b/layout/reftests/css-gradients/linear-percent.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(10% 20%, 80% 90%, from(#0000ff), to(#000000)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(10% 20% 0deg, #0000ff, #000000) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-position-1-ref.html
@@ -0,0 +1,2 @@
+<body style="margin:0;">
+<div style="background: -moz-linear-gradient(left, white, black) no-repeat; position:relative; left:-200px; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-position-1a.html
@@ -0,0 +1,2 @@
+<body style="margin:0;">
+<div style="background: -moz-linear-gradient(left, white, black) no-repeat; background-position:-200px 0; width: 300px; height: 300px;"><br></div>
--- a/layout/reftests/css-gradients/linear-ref.html
+++ b/layout/reftests/css-gradients/linear-ref.html
@@ -1,16 +1,16 @@
 <html xmlns="http://www.w3.org/1999/xhtml" 
       class="reftest-wait">
 <head>
 <script>
 function doDraw() {
   var ctx = document.getElementById('canvas').getContext('2d');
 
-  var grad = ctx.createLinearGradient(10,20,50,100);
+  var grad = ctx.createLinearGradient(0,150,300,150);
   grad.addColorStop(0, 'red');
   grad.addColorStop(1, 'rgb(100, 200, 0)');
   grad.addColorStop(0.5, '#7777FF');
 
   ctx.fillStyle = grad;
   ctx.fillRect(0,0,300,300);
 
   document.documentElement.removeAttribute('class');
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1-ref.html
@@ -0,0 +1,6 @@
+<div style="background: black; width: 300px; height: 50px;"></div>
+<div style="background: white; width: 300px; height: 50px;"></div>
+<div style="background: black; width: 300px; height: 50px;"></div>
+<div style="background: white; width: 300px; height: 50px;"></div>
+<div style="background: black; width: 300px; height: 50px;"></div>
+<div style="background: white; width: 300px; height: 50px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1a.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(black, black 50%, white 50%, white);
+            -moz-background-size: 100px 100px; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1b.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(black, black 50px, white 50px, white 100px, black 100px, black 150px, white 150px, white 200px);
+            -moz-background-size: 100px 200px; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1c.html
@@ -0,0 +1,4 @@
+<div style="background: -moz-linear-gradient(white, white 50%, black 50%, black);
+            -moz-background-size: 100px 100px;
+            background-position: 0 -50px;
+            width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1d.html
@@ -0,0 +1,3 @@
+<div style="background: -moz-linear-gradient(white, white 50px, black 50px, black 100px, white 100px, white 150px, black 150px, black 200px);
+            -moz-background-size: 100px 200px; background-position: 0 -50px;
+            width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1e.html
@@ -0,0 +1,3 @@
+<div style="background: -moz-linear-gradient(black, black 50%, white 50%, white);
+            -moz-background-size: 300px 100px; background-repeat: repeat-y;
+            width: 500px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1f.html
@@ -0,0 +1,10 @@
+<div style="background: -moz-linear-gradient(black, black 50px, white 50px, white 100px, black 100px, black 150px, white 150px, white 200px);
+            -moz-background-size: 100px 200px; background-repeat: repeat-x;
+            width: 300px; height: 800px;
+            margin-bottom: -600px;"></div>
+<!-- making the gradient actually be 300px high isn't reliable since
+     the stop positions cannot be exactly represented and rounding errors
+     creep in. So just let the gradient be 200px high and pad out to match
+     the reference. -->
+<div style="background: black; width: 300px; height: 50px;"></div>
+<div style="background: white; width: 300px; height: 50px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-repeat-1g.html
@@ -0,0 +1,10 @@
+<div style="background: -moz-linear-gradient(black, black 50px, white 50px, white 100px, black 100px, black 150px, white 150px, white 200px);
+            -moz-background-size: 300px 200px; background-repeat: no-repeat;
+            width: 800px; height: 800px;
+            margin-bottom: -600px;"></div>
+<!-- making the gradient actually be 300px high isn't reliable since
+     the stop positions cannot be exactly represented and rounding errors
+     creep in. So just let the gradient be 200px high and pad out to match
+     the reference. -->
+<div style="background: black; width: 300px; height: 50px;"></div>
+<div style="background: white; width: 300px; height: 50px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-size-1-ref.html
@@ -0,0 +1,3 @@
+<div style="background: -moz-linear-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
+<div style="background: -moz-linear-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
+<div style="background: -moz-linear-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-size-1a.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(white, black);
+            -moz-background-size: 300px 100px; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white 0%, red 20%, green 40%, blue 60%, yellow 80%, black 100%) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, red, green, blue, yellow, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white 0, red 60px, green 120px, blue 180px, yellow 240px, black 300px) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1c.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, red 20%, green, blue 60%, yellow, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1d.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, red, green 40%, red 40%, green 40%, blue, yellow, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1e.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, red, green 40%, red 20%, green 40%, blue, yellow, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-stops-1f.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, red, green 40%, red 40%, green 20%, blue, yellow, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-1-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<canvas id="canvas" width="300" height="300"/>
+<script>
+var ctx = document.getElementById('canvas').getContext('2d');
+
+var grad = ctx.createLinearGradient(150,0,150,300);
+grad.addColorStop(0, 'white');
+grad.addColorStop(1, 'black');
+
+ctx.fillStyle = grad;
+ctx.fillRect(0,0,300,300);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-1a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-1b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(top left -90deg, white, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-1c.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white 0%, white 0%, black) no-repeat; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-1d.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(white 0%, white -20%, black) no-repeat; width: 300px; height: 300px;"></div>
--- a/layout/reftests/css-gradients/linear-viewport-ref.html
+++ b/layout/reftests/css-gradients/linear-viewport-ref.html
@@ -1,1 +1,1 @@
-<body style="border: 0; margin: 0; padding: 0;"><div style="background: -moz-linear-gradient(top, bottom, from(blue), to(aqua)) no-repeat; width: 100%; height: 100%;">&nbsp;</div></body>
+<body style="border: 0; margin: 0; padding: 0;"><div style="background: -moz-linear-gradient(blue, aqua) no-repeat; width: 100%; height: 100%;">&nbsp;</div></body>
--- a/layout/reftests/css-gradients/linear-viewport.html
+++ b/layout/reftests/css-gradients/linear-viewport.html
@@ -1,2 +1,2 @@
 <!-- bug 509681 -->
-<body style="background: -moz-linear-gradient(top, bottom, from(blue), to(aqua)) fixed no-repeat;">
+<body style="background: -moz-linear-gradient(blue, aqua) fixed no-repeat;">
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-zero-length-1-ref.html
@@ -0,0 +1,2 @@
+<div style="background: black; width: 300px; height: 300px;"></div>
+<div style="background: black; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-zero-length-1a.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(150px 150px, white, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-linear-gradient(150px 150px, white, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-zero-length-1b.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(150px 150px, white, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-linear-gradient(150px 150px, white, white 100px, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-zero-length-1c.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-linear-gradient(center, white, black 50%); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-linear-gradient(center, white, black 50%); width: 300px; height: 300px;"></div>
--- a/layout/reftests/css-gradients/linear.html
+++ b/layout/reftests/css-gradients/linear.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(10px 20px, 50px 100px, from(red), to(rgb(100, 200, 0)), color-stop(0.5, #7777FF)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(left, red 0%, #7777FF 50%, rgb(100, 200, 0) 100%) no-repeat; width: 300px; height: 300px;"><br></div>
deleted file mode 100644
--- a/layout/reftests/css-gradients/nostops-ref.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" 
-      class="reftest-wait">
-<head>
-<script>
-function doDraw() {
-  var ctx = document.getElementById('canvas').getContext('2d');
-
-  var grad = ctx.createLinearGradient(0,0,150,300);
-
-  ctx.fillStyle = grad;
-  ctx.fillRect(0,0,300,300);
-
-  document.documentElement.removeAttribute('class');
-}
-</script>
-</head>
-<body onload="doDraw();">
-<canvas id="canvas" width="300" height="300"/>
-</body>
-</html>
-
--- a/layout/reftests/css-gradients/nostops.html
+++ b/layout/reftests/css-gradients/nostops.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(left top, center bottom) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(left top) no-repeat; width: 300px; height: 300px;"><br></div>
deleted file mode 100644
--- a/layout/reftests/css-gradients/onestop-ref.html
+++ /dev/null
@@ -1,22 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml" 
-      class="reftest-wait">
-<head>
-<script>
-function doDraw() {
-  var ctx = document.getElementById('canvas').getContext('2d');
-
-  var grad = ctx.createLinearGradient(0,0,150,300);
-  grad.addColorStop(0.5, '#0000ff');
-
-  ctx.fillStyle = grad;
-  ctx.fillRect(0,0,300,300);
-
-  document.documentElement.removeAttribute('class');
-}
-</script>
-</head>
-<body onload="doDraw();">
-<canvas id="canvas" width="300" height="300"/>
-</body>
-</html>
-
--- a/layout/reftests/css-gradients/onestop.html
+++ b/layout/reftests/css-gradients/onestop.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(left top, center bottom, color-stop(0.5, #0000ff)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(left top, #0000ff 50%) no-repeat; width: 300px; height: 300px;"><br></div>
rename from layout/reftests/css-gradients/radial-ref.html
rename to layout/reftests/css-gradients/radial-1-ref.html
--- a/layout/reftests/css-gradients/radial-ref.html
+++ b/layout/reftests/css-gradients/radial-1-ref.html
@@ -1,23 +1,22 @@
-<html xmlns="http://www.w3.org/1999/xhtml" 
+<html xmlns="http://www.w3.org/1999/xhtml"
       class="reftest-wait">
 <head>
 <script>
 function doDraw() {
   var ctx = document.getElementById('canvas').getContext('2d');
 
-  var radgrad = ctx.createRadialGradient(45,45,10,45,45,30);
+  var radgrad = ctx.createRadialGradient(100,100,25,100,100,50);
   radgrad.addColorStop(0, '#FF0000');
   radgrad.addColorStop(1, '#0000FF');
 
   ctx.fillStyle = radgrad;
   ctx.fillRect(0,0,300,300);
 
   document.documentElement.removeAttribute('class');
 }
 </script>
 </head>
 <body onload="doDraw();">
 <canvas id="canvas" width="300" height="300"/>
 </body>
 </html>
-
rename from layout/reftests/css-gradients/radial.html
rename to layout/reftests/css-gradients/radial-1a.html
--- a/layout/reftests/css-gradients/radial.html
+++ b/layout/reftests/css-gradients/radial-1a.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-radial-gradient(45px 45px, 10px, 45px 45px, 30px, from(#ff0000), to(#0000ff)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-radial-gradient(100px 100px, closest-side, #ff0000 25px, #0000ff 50px) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-2-ref.html
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+      class="reftest-wait">
+<head>
+<script>
+function doDraw() {
+  var ctx = document.getElementById('canvas').getContext('2d');
+
+  var radgrad = ctx.createRadialGradient(100,100,0,100,100,50);
+  radgrad.addColorStop(0, '#FF0000');
+  radgrad.addColorStop(1, '#0000FF');
+
+  ctx.fillStyle = radgrad;
+  ctx.fillRect(0,0,300,300);
+
+  document.documentElement.removeAttribute('class');
+}
+</script>
+</head>
+<body onload="doDraw();">
+<canvas id="canvas" width="300" height="300"/>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-2a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-radial-gradient(100px 100px, closest-side, yellow -10px, #ff0000 0, #0000ff 50px); width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-2b.html
@@ -0,0 +1,3 @@
+<!-- This test checks that adjustment of stop positions to be non-negative
+     happens after the calculation of implied stop positions -->
+<div style="background: -moz-radial-gradient(100px 100px, closest-side, #ff0000 -50px, #ff0000, #0000ff 50px); width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-position-1-ref.html
@@ -0,0 +1,2 @@
+<body style="margin:0;">
+<div style="background: -moz-radial-gradient(white, black) no-repeat; position:relative; left:-200px; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-position-1a.html
@@ -0,0 +1,2 @@
+<body style="margin:0;">
+<div style="background: -moz-radial-gradient(white, black) no-repeat; background-position:-200px 0; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-closest-corner-1-ref.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(60px 80px, circle closest-side, white, black 100px); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px, circle closest-side, white, black 100px); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px, circle closest-side, white, black 100px); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px, circle closest-side, white, black 100px); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(60px 80px 90deg, closest-corner, white, black 80px); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px 90deg, closest-corner, white, black 80px); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px 90deg, ellipse closest-corner, white, black 60px); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px 90deg, ellipse closest-corner, white, black 60px); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-closest-corner-1a.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(60px 80px, circle closest-corner, white, black); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px, circle closest-corner, white, black); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px, circle closest-corner, white, black); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px, circle closest-corner, white, black); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(60px 80px, ellipse closest-corner, white, black 60px); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px, ellipse closest-corner, white, black 60px); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px, closest-corner, white, black 80px); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px, closest-corner, white, black 80px); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-closest-side-1-ref.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(50px 80px, circle closest-side, white, black 50px); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(150px 80px, circle closest-side, white, black 50px); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 50px, circle closest-side, white, black 50px); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 150px, circle closest-side, white, black 50px); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(20px 20px, circle closest-side, white, black 20px); height:100px; -moz-transform-origin:0 0; -moz-transform:scale(1.0, 2.0); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(180px 20px, circle closest-side, white, black 20px); height:100px; -moz-transform-origin:0 0; -moz-transform:scale(1.0, 2.0); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(20px 20px, circle closest-side, white, black 20px); width:100px; -moz-transform-origin:0 0; -moz-transform:scale(2.0, 1.0); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(20px 180px, circle closest-side, white, black 20px); width:100px; -moz-transform-origin:0 0; -moz-transform:scale(2.0, 1.0); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-closest-side-1a.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(50px 80px, circle closest-side, white, black); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(150px 80px, circle closest-side, white, black); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 50px, circle closest-side, white, black); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 150px, circle closest-side, white, black); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(20px 40px, ellipse closest-side, white, black); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(180px 40px, ellipse closest-side, white, black); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(40px 20px, closest-side, white, black); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(40px 180px, closest-side, white, black); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-farthest-corner-1-ref.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(40px 80px, circle farthest-side, white, black 200px); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(160px 80px, circle farthest-side, white, black 200px); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 40px, circle farthest-side, white, black 200px); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 160px, circle farthest-side, white, black 200px); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(60px 80px 90deg, farthest-corner, white, black 120px); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px 90deg, farthest-corner, white, black 120px); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px 90deg, ellipse farthest-corner, white, black 140px); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px 90deg, ellipse farthest-corner, white, black 140px); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-farthest-corner-1a.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(40px 80px, circle farthest-corner, white, black); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(160px 80px, circle farthest-corner, white, black); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 40px, circle farthest-corner, white, black); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 160px, circle farthest-corner, white, black); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(60px 80px, ellipse farthest-corner, white, black 140px); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(140px 80px, ellipse farthest-corner, white, black 140px); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 60px, farthest-corner, white, black 120px); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 140px, farthest-corner, white, black 120px); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-farthest-side-1-ref.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(50px 80px, circle farthest-side, white, black 150px); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(150px 80px, circle farthest-side, white, black 150px); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 50px, circle farthest-side, white, black 150px); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 150px, circle farthest-side, white, black 150px); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 80px, circle farthest-side, white, black 120px); -moz-transform-origin:0 0; -moz-transform:scale(1.0, 0.5); top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(120px 120px, circle farthest-side, white, black 120px); -moz-transform-origin:0 0; -moz-transform:scale(1.0, 0.5); top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 80px, circle farthest-side, white, black 120px); -moz-transform-origin:0 0; -moz-transform:scale(0.5, 1.0); top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(120px 120px, circle farthest-side, white, black 120px); -moz-transform-origin:0 0; -moz-transform:scale(0.5, 1.0); top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-shape-farthest-side-1a.html
@@ -0,0 +1,9 @@
+<style>div { position:absolute; width:200px; height:200px; }</style>
+<div style="background: -moz-radial-gradient(50px 80px, circle farthest-side, white, black); top:10px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(150px 80px, circle farthest-side, white, black); top:10px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 50px, circle farthest-side, white, black); top:220px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(80px 150px, circle farthest-side, white, black); top:220px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(80px 40px, farthest-side, white, black); height:100px; top:430px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(120px 60px, farthest-side, white, black); height:100px; top:430px; left:220px;"></div>
+<div style="background: -moz-radial-gradient(40px 80px, ellipse farthest-side, white, black); width:100px; top:640px; left:10px;"></div>
+<div style="background: -moz-radial-gradient(60px 120px, ellipse farthest-side, white, black); width:100px; top:640px; left:220px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-size-1-ref.html
@@ -0,0 +1,3 @@
+<div style="background: -moz-radial-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
+<div style="background: -moz-radial-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
+<div style="background: -moz-radial-gradient(white, black) no-repeat; width: 300px; height: 100px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-size-1a.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(white, black);
+            -moz-background-size: 300px 100px; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1-ref.html
@@ -0,0 +1,2 @@
+<div style="background: black; width: 300px; height: 300px;"></div>
+<div style="background: black; width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1a.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(left, circle closest-side, white, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(left, circle closest-side, white, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1b.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(left, circle closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(left, circle closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1c.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(left, circle closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(left, circle closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1d.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(left, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(left, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1e.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(left, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(left, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/radial-zero-length-1f.html
@@ -0,0 +1,2 @@
+<div style="background: -moz-radial-gradient(top, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
+<div style="background: -moz-repeating-radial-gradient(top, ellipse closest-side, red, white 100px, black); width: 300px; height: 300px;"></div>
--- a/layout/reftests/css-gradients/reftest.list
+++ b/layout/reftests/css-gradients/reftest.list
@@ -1,9 +1,67 @@
 == linear.html linear-ref.html
-== radial.html radial-ref.html
 == linear-keywords.html linear-keywords-ref.html
 == linear-percent.html linear-percent-ref.html
 == linear-mix.html linear-mix-ref.html
-== nostops.html nostops-ref.html
-== onestop.html onestop-ref.html
-== twostops.html twostops-ref.html
+== linear-diagonal-1a.html linear-diagonal-1-ref.html
+== linear-diagonal-1b.html linear-diagonal-1-ref.html
+== linear-diagonal-2a.html linear-diagonal-2-ref.html
+== linear-diagonal-2b.html linear-diagonal-2-ref.html
+== linear-diagonal-3a.html linear-diagonal-3-ref.html
+== linear-diagonal-3b.html linear-diagonal-3-ref.html
+== linear-diagonal-4a.html linear-diagonal-4-ref.html
+== linear-diagonal-4b.html linear-diagonal-4-ref.html
+== linear-diagonal-5a.html linear-diagonal-5-ref.html
+== linear-diagonal-6a.html linear-diagonal-6-ref.html
+== linear-diagonal-7a.html linear-diagonal-7-ref.html
+== linear-diagonal-8a.html linear-diagonal-8-ref.html
+== linear-position-1a.html linear-position-1-ref.html
+== linear-repeat-1a.html linear-repeat-1-ref.html
+== linear-repeat-1b.html linear-repeat-1-ref.html
+== linear-repeat-1c.html linear-repeat-1-ref.html
+== linear-repeat-1d.html linear-repeat-1-ref.html
+== linear-repeat-1e.html linear-repeat-1-ref.html
+== linear-repeat-1f.html linear-repeat-1-ref.html
+== linear-repeat-1g.html linear-repeat-1-ref.html
+== linear-size-1a.html linear-size-1-ref.html
+== linear-stops-1a.html linear-stops-1-ref.html
+== linear-stops-1b.html linear-stops-1-ref.html
+== linear-stops-1c.html linear-stops-1-ref.html
+== linear-stops-1d.html linear-stops-1-ref.html
+== linear-stops-1e.html linear-stops-1-ref.html
+== linear-stops-1f.html linear-stops-1-ref.html
+== linear-vertical-1a.html linear-vertical-1-ref.html
+== linear-vertical-1b.html linear-vertical-1-ref.html
+== linear-vertical-1c.html linear-vertical-1-ref.html
+== linear-vertical-1d.html linear-vertical-1-ref.html
 == linear-viewport.html linear-viewport-ref.html
+== linear-zero-length-1a.html linear-zero-length-1-ref.html
+== linear-zero-length-1b.html linear-zero-length-1-ref.html
+== linear-zero-length-1c.html linear-zero-length-1-ref.html
+== nostops.html about:blank
+== onestop.html about:blank
+== radial-1a.html radial-1-ref.html
+== radial-2a.html radial-2-ref.html
+== radial-2b.html radial-2-ref.html
+== radial-position-1a.html radial-position-1-ref.html
+== radial-shape-closest-corner-1a.html radial-shape-closest-corner-1-ref.html
+== radial-shape-closest-side-1a.html radial-shape-closest-side-1-ref.html
+== radial-shape-farthest-corner-1a.html radial-shape-farthest-corner-1-ref.html
+== radial-shape-farthest-side-1a.html radial-shape-farthest-side-1-ref.html
+== radial-size-1a.html radial-size-1-ref.html
+== radial-zero-length-1a.html radial-zero-length-1-ref.html
+== radial-zero-length-1b.html radial-zero-length-1-ref.html
+== radial-zero-length-1c.html radial-zero-length-1-ref.html
+== radial-zero-length-1d.html radial-zero-length-1-ref.html
+== radial-zero-length-1e.html radial-zero-length-1-ref.html
+== radial-zero-length-1f.html radial-zero-length-1-ref.html
+== repeating-linear-1a.html repeating-linear-1-ref.html
+== repeating-linear-1b.html repeating-linear-1-ref.html
+== repeating-linear-2a.html repeating-linear-2-ref.html
+== repeating-radial-1a.html repeating-radial-1-ref.html
+== repeating-radial-1b.html repeating-radial-1-ref.html
+== repeating-radial-2a.html repeating-radial-2-ref.html
+== twostops-1a.html twostops-1-ref.html
+== twostops-1b.html twostops-1-ref.html
+fails == twostops-1c.html twostops-1-ref.html # bug 524173
+== twostops-1d.html twostops-1-ref.html
+fails-if(MOZ_WIDGET_TOOLKIT!="cocoa") == twostops-1e.html twostops-1-ref.html # bug 524173
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-linear-1-ref.html
@@ -0,0 +1,8 @@
+<div style="background: black; width: 400px; height: 50px;"></div>
+<div style="background: white; width: 400px; height: 50px;"></div>
+<div style="background: black; width: 400px; height: 50px;"></div>
+<div style="background: white; width: 400px; height: 50px;"></div>
+<div style="background: black; width: 400px; height: 50px;"></div>
+<div style="background: white; width: 400px; height: 50px;"></div>
+<div style="background: black; width: 400px; height: 50px;"></div>
+<div style="background: white; width: 400px; height: 50px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-linear-1a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-linear-gradient(black 0, black 50px, white 50px, white 100px); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-linear-1b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-linear-gradient(black 100px, black 150px, white 150px, white 200px); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-linear-2-ref.html
@@ -0,0 +1,1 @@
+<div style="width:300px; height:300px; background:blue;"></div>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-linear-2a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-linear-gradient(red 20px, blue 20px); width: 300px; height: 300px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-radial-1-ref.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-radial-gradient(closest-side, black 0, black 50px, white 50px, white 100px); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-radial-1a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-radial-gradient(closest-side, black 100px, black 150px, white 150px, white 200px); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-radial-1b.html
@@ -0,0 +1,4 @@
+<!-- Test adjustment of negative stop positions in a repeating radial gradient.
+     We should still get a repeating pattern, i.e., the stops cannot
+     naively be mapped to 0. -->
+<div style="background: -moz-repeating-radial-gradient(closest-side, black -100px, black -50px, white -50px, white 0); width: 400px; height: 400px;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-radial-2-ref.html
@@ -0,0 +1,1 @@
+<div style="width:300px; height:300px; background:blue;"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/repeating-radial-2a.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-repeating-radial-gradient(red 20px, blue 20px); width: 300px; height: 300px;"></div>
rename from layout/reftests/css-gradients/twostops-ref.html
rename to layout/reftests/css-gradients/twostops-1-ref.html
--- a/layout/reftests/css-gradients/twostops-ref.html
+++ b/layout/reftests/css-gradients/twostops-1-ref.html
@@ -1,23 +1,7 @@
-<html xmlns="http://www.w3.org/1999/xhtml" 
-      class="reftest-wait">
-<head>
-<script>
-function doDraw() {
-  var ctx = document.getElementById('canvas').getContext('2d');
-
-  var grad = ctx.createLinearGradient(0,0,150,300);
-  grad.addColorStop(0.5, '#0000ff');
-  grad.addColorStop(0.5, '#ff0000');
-
-  ctx.fillStyle = grad;
-  ctx.fillRect(0,0,300,300);
-
-  document.documentElement.removeAttribute('class');
-}
-</script>
-</head>
-<body onload="doDraw();">
-<canvas id="canvas" width="300" height="300"/>
+<!DOCTYPE HTML>
+<html>
+<body>
+<div style="background:#0000ff; width:300px; height:150px;"></div>
+<div style="background:#ff0000; width:300px; height:150px;"></div>
 </body>
 </html>
-
rename from layout/reftests/css-gradients/twostops.html
rename to layout/reftests/css-gradients/twostops-1a.html
--- a/layout/reftests/css-gradients/twostops.html
+++ b/layout/reftests/css-gradients/twostops-1a.html
@@ -1,1 +1,1 @@
-<div style="background: -moz-linear-gradient(left top, center bottom, color-stop(0.5, #0000ff), color-stop(0.5, #ff0000)) no-repeat; width: 300px; height: 300px;"><br></div>
+<div style="background: -moz-linear-gradient(top, #0000ff 50%, #ff0000 50%) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/twostops-1b.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(bottom, #ff0000 50%, #0000ff 50%) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/twostops-1c.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(yellow -50%, #0000ff 0, #0000ff 50%, #ff0000 50%) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/twostops-1d.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(#0000ff 50%, #ff0000 50%, #ff0000 100%, yellow 150%) no-repeat; width: 300px; height: 300px;"><br></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/twostops-1e.html
@@ -0,0 +1,1 @@
+<div style="background: -moz-linear-gradient(yellow -50%, #0000ff 0, #0000ff 50%, #ff0000 50%, #ff0000 100%, yellow 150%) no-repeat; width: 300px; height: 300px;"><br></div>
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -49,17 +49,17 @@ class nsString;
 enum nsStyleUnit {
   eStyleUnit_Null         = 0,      // (no value) value is not specified
   eStyleUnit_Normal       = 1,      // (no value)
   eStyleUnit_Auto         = 2,      // (no value)
   eStyleUnit_None         = 3,      // (no value)
   eStyleUnit_Percent      = 10,     // (float) 1.0 == 100%
   eStyleUnit_Factor       = 11,     // (float) a multiplier
   eStyleUnit_Degree       = 12,     // (float) angle in degrees
-  eStyleUnit_Grad         = 13,     // (float) angle in radians
+  eStyleUnit_Grad         = 13,     // (float) angle in grads
   eStyleUnit_Radian       = 14,     // (float) angle in radians
   eStyleUnit_Coord        = 20,     // (nscoord) value is twips
   eStyleUnit_Integer      = 30,     // (int) value is simple integer
   eStyleUnit_Enumerated   = 32      // (int) value has enumerated meaning
 };
 
 typedef union {
   PRInt32     mInt;   // nscoord is a PRInt32 for now
@@ -88,16 +88,20 @@ public:
   PRBool         operator==(const nsStyleCoord& aOther) const;
   PRBool         operator!=(const nsStyleCoord& aOther) const;
 
   nsStyleUnit GetUnit(void) const {
     NS_ASSERTION(mUnit != eStyleUnit_Null, "reading uninitialized value");
     return mUnit;
   }
 
+  PRBool IsAngleValue(void) const {
+    return eStyleUnit_Degree <= mUnit && mUnit <= eStyleUnit_Radian;
+  }
+
   nscoord     GetCoordValue(void) const;
   PRInt32     GetIntValue(void) const;
   float       GetPercentValue(void) const;
   float       GetFactorValue(void) const;
   float       GetAngleValue(void) const;
   double      GetAngleValueInRadians(void) const;
   void        GetUnionValue(nsStyleUnion& aValue) const;
 
--- a/toolkit/themes/pinstripe/global/shared.inc
+++ b/toolkit/themes/pinstripe/global/shared.inc
@@ -1,34 +1,34 @@
 %filter substitution
 
 %define loweredShadow 0 1px rgba(255, 255, 255, .4)
 %define focusRingShadow 0 0 1px -moz-mac-focusring inset, 0 0 4px 1px -moz-mac-focusring, 0 0 2px 1px -moz-mac-focusring
 
 %define roundButtonBorder 1px solid rgba(0, 0, 0, .4)
-%define roundButtonBackground -moz-linear-gradient(top, bottom, from(#FFF), to(#CACACA)) repeat-x
+%define roundButtonBackground -moz-linear-gradient(top, bottom, #FFF, #CACACA) repeat-x
 %define roundButtonShadow 0 1px rgba(255, 255, 255, .4)
 %define roundButtonPressedBackground #CCC
 %define roundButtonPressedShadow inset 0 1px 4px rgba(0, 0, 0, .2), 0 1px rgba(255, 255, 255, .4)
 
-%define scopeBarBackground -moz-linear-gradient(top, bottom, from(#E8E8E8), to(#D0D0D0)) repeat-x
+%define scopeBarBackground -moz-linear-gradient(top, bottom, #E8E8E8, #D0D0D0) repeat-x
 %define scopeBarSeparatorBorder 1px solid #888
 %define scopeBarTitleColor #6D6D6D
 
 %define sidebarItemBorderTop 1px solid #94A1C0
-%define sidebarItemBackground -moz-linear-gradient(top, bottom, from(#A0B0CF), to(#7386AB)) repeat-x
+%define sidebarItemBackground -moz-linear-gradient(top, bottom, #A0B0CF, #7386AB) repeat-x
 %define sidebarItemFocusedBorderTop 1px solid #5382C5
-%define sidebarItemFocusedBackground -moz-linear-gradient(top, bottom, from(#6494D4), to(#2559AC)) repeat-x
+%define sidebarItemFocusedBackground -moz-linear-gradient(top, bottom, #6494D4, #2559AC) repeat-x
 %define sidebarItemGraphiteBorderTop 1px solid #97A4B1
-%define sidebarItemGraphiteBackground -moz-linear-gradient(top, bottom, from(#AAB7C4), to(#8393A4)) repeat-x
+%define sidebarItemGraphiteBackground -moz-linear-gradient(top, bottom, #AAB7C4, #8393A4) repeat-x
 %define sidebarItemGraphiteFocusedBorderTop 1px solid #6B798D
-%define sidebarItemGraphiteFocusedBackground -moz-linear-gradient(top, bottom, from(#8293A6), to(#425972)) repeat-x
+%define sidebarItemGraphiteFocusedBackground -moz-linear-gradient(top, bottom, #8293A6, #425972) repeat-x
 %define sidebarItemInactiveBorderTop 1px solid #979797
-%define sidebarItemInactiveBackground -moz-linear-gradient(top, bottom, from(#B4B4B4), to(#8A8A8A)) repeat-x
+%define sidebarItemInactiveBackground -moz-linear-gradient(top, bottom, #B4B4B4, #8A8A8A) repeat-x
 
 %define toolbarbuttonBorderColor rgba(59, 59, 59, 0.9)
 %define toolbarbuttonCornerRadius 3px
-%define toolbarbuttonBackground -moz-linear-gradient(top, bottom, from(#FFF), to(#ADADAD)) repeat-x
+%define toolbarbuttonBackground -moz-linear-gradient(top, bottom, #FFF, #ADADAD) repeat-x
 %define toolbarbuttonPressedInnerShadow inset rgba(0, 0, 0, 0.3) 0 -6px 14px, inset #000 0 1px 4px, inset rgba(0, 0, 0, 0.2) 0 1px 4px
 %define toolbarbuttonPressedBackgroundColor #B5B5B5
 %define toolbarbuttonInactiveBorderColor rgba(146, 146, 146, 0.84)
 %define toolbarbuttonInactiveFontColor #7C7C7C
-%define toolbarbuttonInactiveBackgroundImage -moz-linear-gradient(top, bottom, from(#FFF), to(#CCC))
+%define toolbarbuttonInactiveBackgroundImage -moz-linear-gradient(top, bottom, #FFF, #CCC)