[SCM] WebKit Debian packaging branch, debian/experimental, updated. debian/1.3.8-1-1049-g2e11a8e

simon.fraser at apple.com simon.fraser at apple.com
Fri Jan 21 14:52:31 UTC 2011


The following commit has been merged in the debian/experimental branch:
commit 9706826b9ebb4ea55602c4d1a4adfd91edde1a6f
Author: simon.fraser at apple.com <simon.fraser at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Jan 3 19:31:32 2011 +0000

    2011-01-03  Simon Fraser  <simon.fraser at apple.com>
    
            Reviewed by David Hyatt.
    
            Implement -webkit-linear-gradient and -webkit-radial-gradient
            https://bugs.webkit.org/show_bug.cgi?id=28152
    
            Add support for the parsing and rendering of non-repeating CSS3 linear gradients,
            according to <http://dev.w3.org/csswg/css3-images/#linear-gradients>.
    
            Tests: fast/gradients/css3-color-stop-units.html
                   fast/gradients/css3-color-stops.html
                   fast/gradients/css3-gradient-parsing.html
                   fast/gradients/css3-linear-angle-gradients.html
    
            * css/CSSGradientValue.h:
            Add subclasses of CSSGradientValue for linear and radial gradients.
    
            * css/CSSGradientValue.cpp:
            (WebCore::CSSGradientValue::image): Add FIXME comment about why we can't cache
            the gradient sometimes.
            (WebCore::compareStops): positions are CSSValues now.
            (WebCore::CSSGradientValue::sortStopsIfNeeded): Add assertion that this is only called
            for old-style gradients.
            (WebCore::CSSGradientValue::addStops): New method that handles the spec rules about
            missing positions, ensuring that stop position is ordered, and spacing out stops
            without positions. Also normalize gradients which use stops outside the 0-1 range
            so that platforms can render them correctly.
            (WebCore::positionFromValue): Determin the position on the gradient line for percentage,
            number and length values.
            (WebCore::CSSGradientValue::computeEndPoint):
            (WebCore::CSSLinearGradientValue::cssText):
            (WebCore::endPointsFromAngle): Compute endpoints for a gradient which covers the rectangle
            given an angle.
            (WebCore::CSSLinearGradientValue::createGradient):
            (WebCore::CSSRadialGradientValue::cssText):
            (WebCore::CSSRadialGradientValue::resolveRadius):
            (WebCore::CSSRadialGradientValue::createGradient):
    
            * css/CSSParser.cpp:
            (WebCore::CSSParser::parseValue): Style fix.
            (WebCore::CSSParser::parseContent): Use isGeneratedImageValue() and parseGeneratedImage()
            (WebCore::CSSParser::parseFillImage): Use isGeneratedImageValue() and parseGeneratedImage()
            (WebCore::CSSParser::parseBorderImage): Use isGeneratedImageValue() and parseGeneratedImage()
            (WebCore::parseDeprecatedGradientPoint): Renamed to indicate that it's only used for -webkit-gradient.
            (WebCore::parseDeprecatedGradientColorStop): Renamed to indicate that it's only used for -webkit-gradient,
            and fixed to store CSSValues for the stop position.
            (WebCore::CSSParser::parseDeprecatedGradient): Renamed to indicate that it's only used for -webkit-gradient,
            and create CSSLinearGradientValue and CSSRadialGradientValue as appropriate.
            (WebCore::valueFromSideKeyword):
            (WebCore::parseGradientColorOrKeyword): Color parsing utility.
            (WebCore::CSSParser::parseLinearGradient): New method to parse linear gradients.
            (WebCore::CSSParser::parseRadialGradient): Stub for new method to parse radial gradients.
            (WebCore::CSSParser::isGeneratedImageValue): Detect gradients and CSS canvas.
            (WebCore::CSSParser::parseGeneratedImage): Parser for generated images like gradients
            and CSS canvas.
            * css/CSSParser.h:
            * platform/graphics/Gradient.h:
            (WebCore::Gradient::setP0): We need to be able to change the points when normalizing gradients.
            (WebCore::Gradient::setP1): Ditto.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74912 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 04f284a..5510929 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,27 @@
+2011-01-03  Simon Fraser  <simon.fraser at apple.com>
+
+        Reviewed by David Hyatt.
+
+        Implement -webkit-linear-gradient and -webkit-radial-gradient
+        https://bugs.webkit.org/show_bug.cgi?id=28152
+        
+        Testcases for CSS3 linear-gradients.
+
+        * fast/gradients/css3-color-stop-units-expected.txt: Added.
+        * fast/gradients/css3-color-stop-units.html: Added.
+        * fast/gradients/css3-color-stops-expected.txt: Added.
+        * fast/gradients/css3-color-stops.html: Added.
+        * fast/gradients/css3-gradient-parsing-expected.txt: Added.
+        * fast/gradients/css3-gradient-parsing.html: Added.
+        * fast/gradients/css3-linear-angle-gradients-expected.txt: Added.
+        * fast/gradients/css3-linear-angle-gradients.html: Added.
+        * platform/mac/fast/gradients/css3-color-stop-units-expected.checksum: Added.
+        * platform/mac/fast/gradients/css3-color-stop-units-expected.png: Added.
+        * platform/mac/fast/gradients/css3-color-stops-expected.checksum: Added.
+        * platform/mac/fast/gradients/css3-color-stops-expected.png: Added.
+        * platform/mac/fast/gradients/css3-linear-angle-gradients-expected.checksum: Added.
+        * platform/mac/fast/gradients/css3-linear-angle-gradients-expected.png: Added.
+
 2011-01-03  Mihai Parparita  <mihaip at chromium.org>
 
         Unreviewed, Chromium test expectation update.
diff --git a/LayoutTests/fast/gradients/css3-color-stop-units-expected.txt b/LayoutTests/fast/gradients/css3-color-stop-units-expected.txt
new file mode 100644
index 0000000..6c158c3
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-color-stop-units-expected.txt
@@ -0,0 +1,8 @@
+These should look the same
+ 
+Green stop should coincide with the end of the black line
+ 
+Should see a sharp green/yellow transition on the right, at the end of the line
+ 
+Should see a sharp green/yellow transition in the right box
+ 
diff --git a/LayoutTests/fast/gradients/css3-color-stop-units.html b/LayoutTests/fast/gradients/css3-color-stop-units.html
new file mode 100644
index 0000000..2787876
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-color-stop-units.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    h2 {
+      font-size: 12pt;
+      margin: 2px;
+    }
+
+    .box {
+      display: inline-block;
+      height: 100px;
+      width: 300px;
+      margin: 10px;
+      border: 1px solid black;
+      background-repeat: no-repeat;
+    }
+
+    .indicator {
+      background-color: black;
+      height: 20px;
+      width: 3em;
+    }
+
+    .linear1 {
+      background-image: -webkit-linear-gradient(left, red, green 33.33%, blue);
+      background-image: -moz-linear-gradient(left, red, green 33.33%, blue);
+    }
+
+    .linear2 {
+      background-image: -webkit-linear-gradient(left, red, green 100px, blue);
+      background-image: -moz-linear-gradient(left, red, green 100px, blue);
+    }
+
+    .linear3 {
+      font-size: 12pt;
+      background-image: -webkit-linear-gradient(left, red, green 3em, blue);
+      background-image: -moz-linear-gradient(left, red, green 3em, blue);
+    }
+
+    .linear4 {
+      font-size: 24pt;
+      background-image: -webkit-linear-gradient(left, red, green 3em, blue);
+      background-image: -moz-linear-gradient(left, red, green 3em, blue);
+    }
+
+    .linear5 {
+      font-size: 12pt;
+      background-image: -webkit-linear-gradient(left, red, green 6em, yellow 50%, blue);
+      background-image: -moz-linear-gradient(left, red, green 6em, yellow 50%, blue);
+    }
+
+    .linear6 {
+      font-size: 24pt;
+      background-image: -webkit-linear-gradient(left, red, green 6em, yellow 50%, blue);
+      background-image: -moz-linear-gradient(left, red, green 6em, yellow 50%, blue);
+    }
+
+    .linear7 {
+      background-image: -webkit-linear-gradient(left, red, green 100px, yellow 50%, blue);
+      background-image: -moz-linear-gradient(left, red, green 100px, yellow 50%, blue);
+    }
+
+    .linear8 {
+      background-image: -webkit-linear-gradient(left, red, green 100px, yellow 50%, blue);
+      background-image: -moz-linear-gradient(left, red, green 100px, yellow 50%, blue);
+    }
+  </style>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+      var dumpPixels = true;
+      layoutTestController.dumpAsText(dumpPixels);
+    }
+  </script>
+</head>
+<body>
+
+  <h2>These should look the same</h2>
+  <div class="container">
+    <div class="linear1 box"></div>
+    <div class="linear2 box"></div>
+  </div>
+
+  <h2>Green stop should coincide with the end of the black line</h2>
+  <div class="container">
+    <div class="linear3 box"><div class="indicator" style="width: 3em;"></div></div>
+    <div class="linear4 box"><div class="indicator" style="width: 3em;"></div></div>
+  </div>
+
+  <h2>Should see a sharp green/yellow transition on the right, at the end of the line</h2>
+  <div class="container">
+    <div class="linear5 box"><div class="indicator" style="width: 6em;"></div></div>
+    <div class="linear6 box"><div class="indicator" style="width: 6em;"></div></div>
+  </div>
+
+  <h2>Should see a sharp green/yellow transition in the right box</h2>
+  <div class="container">
+    <div class="linear7 box"></div>
+    <div class="linear8 box" style="width: 200px;"></div>
+  </div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/gradients/css3-color-stops-expected.txt b/LayoutTests/fast/gradients/css3-color-stops-expected.txt
new file mode 100644
index 0000000..a0cc541
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-color-stops-expected.txt
@@ -0,0 +1,3 @@
+   
+   
+  
diff --git a/LayoutTests/fast/gradients/css3-color-stops.html b/LayoutTests/fast/gradients/css3-color-stops.html
new file mode 100644
index 0000000..4509f4e
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-color-stops.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .box {
+      display: inline-block;
+      height: 120px;
+      width: 200px;
+      margin: 10px;
+      border: 1px solid black;
+      background-repeat: no-repeat;
+    }
+
+    .linear1 {
+      background-image: -webkit-linear-gradient(left, black);
+      background-image: -moz-linear-gradient(left, black);
+    }
+
+    .linear2 {
+      background-image: -webkit-linear-gradient(left, white, black);
+      background-image: -moz-linear-gradient(left, white, black);
+    }
+
+    .linear3 {
+      background-image: -webkit-linear-gradient(left, red, green, blue);
+      background-image: -moz-linear-gradient(left, red, green, blue);
+    }
+
+    .linear4 {
+      background-image: -webkit-linear-gradient(left, red 25%, green 50%, blue 75%);
+      background-image: -moz-linear-gradient(left, red 25%, green 50%, blue 75%);
+    }
+
+    .linear5 {
+      /* Green should get shifted to 50% */
+      background-image: -webkit-linear-gradient(left, red 50%, green 30%, blue 90%);
+      background-image: -moz-linear-gradient(left, red 50%, green 30%, blue 90%);
+    }
+
+    .linear6 {
+      /* Green and yellow should be evenly spaced */
+      background-image: -webkit-linear-gradient(left, red, yellow, green, blue);
+      background-image: -moz-linear-gradient(left, red, yellow, green, blue);
+    }
+
+    .linear7 {
+      background-image: -webkit-linear-gradient(red -50%, green, blue, green, blue 150%);
+      background-image: -moz-linear-gradient(red -50%, green, blue, green, blue 150%);
+    }
+
+    .linear8 {
+      background-image: -webkit-linear-gradient(left, red, green 100px, blue);
+      background-image: -moz-linear-gradient(left, red, green 100px, blue);
+    }
+
+    .linear9 {
+      background-image: -webkit-linear-gradient(left, red, green 120%, blue);
+      background-image: -moz-linear-gradient(left, red, green 120%, blue);
+    }
+  </style>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+      var dumpPixels = true;
+      layoutTestController.dumpAsText(dumpPixels);
+    }
+  </script>
+</head>
+<body>
+
+  <div class="linear1 box"></div>
+  <div class="linear2 box"></div>
+  <div class="linear3 box"></div>
+  <br>
+  <div class="linear4 box"></div>
+  <div class="linear5 box"></div>
+  <div class="linear6 box"></div>
+  <br>
+  <div class="linear7 box"></div>
+  <div class="linear8 box"></div>
+  <div class="linear9 box"></div>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/gradients/css3-gradient-parsing-expected.txt b/LayoutTests/fast/gradients/css3-gradient-parsing-expected.txt
new file mode 100644
index 0000000..3e60e8a
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-gradient-parsing-expected.txt
@@ -0,0 +1,25 @@
+Tests -webkit-linear-gradient and -webkit-radial-gradient
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS testGradient("background-image: -webkit-linear-gradient(black 0%", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(top)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(10deg)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(top center, black 0%)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(10px 20%, black 0%)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(left left)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(left center)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(left 10deg, black 0%)", "background-image") is "none"
+PASS testGradient("background-image: -webkit-linear-gradient(black 0)", "background-image") is "-webkit-linear-gradient(top, black 0px)"
+PASS testGradient("background-image: -webkit-linear-gradient(black 0%)", "background-image") is "-webkit-linear-gradient(top, black 0%)"
+PASS testGradient("background-image: -webkit-linear-gradient(black 0%)", "background-image") is "-webkit-linear-gradient(top, black 0%)"
+PASS testGradient("background-image: -webkit-linear-gradient(black, white)", "background-image") is "-webkit-linear-gradient(top, black, white)"
+PASS testGradient("background-image: -webkit-linear-gradient(black 10px, white 20px)", "background-image") is "-webkit-linear-gradient(top, black 10px, white 20px)"
+PASS testGradient("background-image: -webkit-linear-gradient(top left, black 0%)", "background-image") is "-webkit-linear-gradient(left top, black 0%)"
+PASS testGradient("background-image: -webkit-linear-gradient(top, black 0%)", "background-image") is "-webkit-linear-gradient(top, black 0%)"
+PASS testGradient("background-image: -webkit-linear-gradient(10deg, black 0%)", "background-image") is "-webkit-linear-gradient(10deg, black 0%)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/gradients/css3-gradient-parsing.html b/LayoutTests/fast/gradients/css3-gradient-parsing.html
new file mode 100644
index 0000000..3d07f70
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-gradient-parsing.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+
+
+<script type="text/javascript">
+description('Tests -webkit-linear-gradient and -webkit-radial-gradient');
+
+function testGradient(css, queryProp)
+{
+    var div = document.createElement('div');
+    div.setAttribute('style', css);
+    document.body.appendChild(div);
+
+    var result = getComputedStyle(div).getPropertyValue(queryProp);
+    document.body.removeChild(div);
+    return result;
+}
+
+function testSame(dir, prop, altProp, value)
+{
+    shouldBeEqualToString('test("' + dir + '", "' + prop + ': ' + value + '", "' + altProp + '")', value);
+    shouldBeEqualToString('test("' + dir + '", "' + altProp + ': ' + value + '", "' + prop + '")', value);
+}
+
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black 0%", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(top)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(10deg)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(top center, black 0%)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(10px 20%, black 0%)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(left left)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(left center)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(left 10deg, black 0%)", "background-image")', '"none"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black 0)", "background-image")', '"-webkit-linear-gradient(top, black 0px)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black 0%)", "background-image")', '"-webkit-linear-gradient(top, black 0%)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black 0%)", "background-image")', '"-webkit-linear-gradient(top, black 0%)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black, white)", "background-image")', '"-webkit-linear-gradient(top, black, white)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(black 10px, white 20px)", "background-image")', '"-webkit-linear-gradient(top, black 10px, white 20px)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(top left, black 0%)", "background-image")', '"-webkit-linear-gradient(left top, black 0%)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(top, black 0%)", "background-image")', '"-webkit-linear-gradient(top, black 0%)"');
+shouldBe('testGradient("background-image: -webkit-linear-gradient(10deg, black 0%)", "background-image")', '"-webkit-linear-gradient(10deg, black 0%)"');
+
+successfullyParsed = true;
+  
+</script>
+
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/gradients/css3-linear-angle-gradients-expected.txt b/LayoutTests/fast/gradients/css3-linear-angle-gradients-expected.txt
new file mode 100644
index 0000000..a0cc541
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-linear-angle-gradients-expected.txt
@@ -0,0 +1,3 @@
+   
+   
+  
diff --git a/LayoutTests/fast/gradients/css3-linear-angle-gradients.html b/LayoutTests/fast/gradients/css3-linear-angle-gradients.html
new file mode 100644
index 0000000..f076096
--- /dev/null
+++ b/LayoutTests/fast/gradients/css3-linear-angle-gradients.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+  <style type="text/css" media="screen">
+    .box {
+      display: inline-block;
+      height: 120px;
+      width: 200px;
+      margin: 10px;
+      border: 1px solid black;
+      background-repeat: no-repeat;
+    }
+
+    .linear1 {
+      background-image: -webkit-linear-gradient(white, black);
+      background-image: -moz-linear-gradient(white, black);
+    }
+    
+    .linear2 {
+      background-image: -webkit-linear-gradient(top left, white, black);
+      background-image: -moz-linear-gradient(top left, white, black);
+    }
+
+    .linear3 {
+      background-image: -webkit-linear-gradient(45deg, white, black);
+      background-image: -moz-linear-gradient(45deg, white, black);
+    }
+
+    .linear4 {
+      background-image: -webkit-linear-gradient(-45deg, white, black);
+      background-image: -moz-linear-gradient(-45deg, white, black);
+    }
+
+    .linear5 {
+      background-image: -webkit-linear-gradient(540deg, white, black);
+      background-image: -moz-linear-gradient(540deg, white, black);
+    }
+
+    .linear6 {
+      background-image: -webkit-linear-gradient(top left, white -20%, black 120%);
+      background-image: -moz-linear-gradient(top left, white -20%, black 120%);
+    }
+
+    .linear7 {
+      background-image: -webkit-linear-gradient(top left, white -20px, black 120px);
+      background-image: -moz-linear-gradient(top left, white -20px, black 120px);
+    }
+
+    .linear8 {
+      background-image: -webkit-linear-gradient(top left, white -20%, blue, black 120%);
+      background-image: -moz-linear-gradient(top left, white -20%, blue, black 120%);
+    }
+
+    .linear9 {
+      background-image: -webkit-linear-gradient(0deg, white -20%, blue, black 120%);
+      background-image: -moz-linear-gradient(0deg, white -20%, blue, black 120%);
+    }
+  </style>
+  <script type="text/javascript" charset="utf-8">
+    if (window.layoutTestController) {
+      var dumpPixels = true;
+      layoutTestController.dumpAsText(dumpPixels);
+    }
+  </script>
+</head>
+<body>
+
+  <div class="linear1 box"></div>
+  <div class="linear2 box"></div>
+  <div class="linear3 box"></div>
+  <br>
+  <div class="linear4 box"></div>
+  <div class="linear5 box"></div>
+  <div class="linear6 box"></div>
+  <br>
+  <div class="linear7 box"></div>
+  <div class="linear8 box"></div>
+  <div class="linear9 box"></div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.checksum b/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.checksum
new file mode 100644
index 0000000..24cf857
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.checksum
@@ -0,0 +1 @@
+0555575fa54aa36eec7bed483a3420a1
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.png b/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.png
new file mode 100644
index 0000000..25676c3
Binary files /dev/null and b/LayoutTests/platform/mac/fast/gradients/css3-color-stop-units-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.checksum b/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.checksum
new file mode 100644
index 0000000..1b56ad6
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.checksum
@@ -0,0 +1 @@
+8a00529ff6bbdb22a5b1e1c9ca03c501
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.png b/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.png
new file mode 100644
index 0000000..03acfe0
Binary files /dev/null and b/LayoutTests/platform/mac/fast/gradients/css3-color-stops-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.checksum b/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.checksum
new file mode 100644
index 0000000..a2b52c9
--- /dev/null
+++ b/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.checksum
@@ -0,0 +1 @@
+6d41e543cd9a3ad2339243331b34dae2
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.png b/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.png
new file mode 100644
index 0000000..f34927e
Binary files /dev/null and b/LayoutTests/platform/mac/fast/gradients/css3-linear-angle-gradients-expected.png differ
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 9fc9564..5a7c342 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,64 @@
+2011-01-03  Simon Fraser  <simon.fraser at apple.com>
+
+        Reviewed by David Hyatt.
+
+        Implement -webkit-linear-gradient and -webkit-radial-gradient
+        https://bugs.webkit.org/show_bug.cgi?id=28152
+        
+        Add support for the parsing and rendering of non-repeating CSS3 linear gradients,
+        according to <http://dev.w3.org/csswg/css3-images/#linear-gradients>.
+
+        Tests: fast/gradients/css3-color-stop-units.html
+               fast/gradients/css3-color-stops.html
+               fast/gradients/css3-gradient-parsing.html
+               fast/gradients/css3-linear-angle-gradients.html
+
+        * css/CSSGradientValue.h:
+        Add subclasses of CSSGradientValue for linear and radial gradients.
+        
+        * css/CSSGradientValue.cpp:
+        (WebCore::CSSGradientValue::image): Add FIXME comment about why we can't cache
+        the gradient sometimes.
+        (WebCore::compareStops): positions are CSSValues now.
+        (WebCore::CSSGradientValue::sortStopsIfNeeded): Add assertion that this is only called
+        for old-style gradients.
+        (WebCore::CSSGradientValue::addStops): New method that handles the spec rules about
+        missing positions, ensuring that stop position is ordered, and spacing out stops
+        without positions. Also normalize gradients which use stops outside the 0-1 range
+        so that platforms can render them correctly.
+        (WebCore::positionFromValue): Determin the position on the gradient line for percentage,
+        number and length values.
+        (WebCore::CSSGradientValue::computeEndPoint):
+        (WebCore::CSSLinearGradientValue::cssText):
+        (WebCore::endPointsFromAngle): Compute endpoints for a gradient which covers the rectangle
+        given an angle.
+        (WebCore::CSSLinearGradientValue::createGradient):
+        (WebCore::CSSRadialGradientValue::cssText):
+        (WebCore::CSSRadialGradientValue::resolveRadius):
+        (WebCore::CSSRadialGradientValue::createGradient):
+
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseValue): Style fix.
+        (WebCore::CSSParser::parseContent): Use isGeneratedImageValue() and parseGeneratedImage()
+        (WebCore::CSSParser::parseFillImage): Use isGeneratedImageValue() and parseGeneratedImage()
+        (WebCore::CSSParser::parseBorderImage): Use isGeneratedImageValue() and parseGeneratedImage()
+        (WebCore::parseDeprecatedGradientPoint): Renamed to indicate that it's only used for -webkit-gradient.
+        (WebCore::parseDeprecatedGradientColorStop): Renamed to indicate that it's only used for -webkit-gradient,
+        and fixed to store CSSValues for the stop position.
+        (WebCore::CSSParser::parseDeprecatedGradient): Renamed to indicate that it's only used for -webkit-gradient,
+        and create CSSLinearGradientValue and CSSRadialGradientValue as appropriate.
+        (WebCore::valueFromSideKeyword):
+        (WebCore::parseGradientColorOrKeyword): Color parsing utility.
+        (WebCore::CSSParser::parseLinearGradient): New method to parse linear gradients.
+        (WebCore::CSSParser::parseRadialGradient): Stub for new method to parse radial gradients.
+        (WebCore::CSSParser::isGeneratedImageValue): Detect gradients and CSS canvas.
+        (WebCore::CSSParser::parseGeneratedImage): Parser for generated images like gradients
+        and CSS canvas.
+        * css/CSSParser.h:
+        * platform/graphics/Gradient.h:
+        (WebCore::Gradient::setP0): We need to be able to change the points when normalizing gradients.
+        (WebCore::Gradient::setP1): Ditto.
+
 2011-01-03  Noam Rosenthal  <noam.rosenthal at nokia.com>
 
         Reviewed by Andreas Kling.
diff --git a/WebCore/css/CSSGradientValue.cpp b/WebCore/css/CSSGradientValue.cpp
index 5946d7a..ca65709 100644
--- a/WebCore/css/CSSGradientValue.cpp
+++ b/WebCore/css/CSSGradientValue.cpp
@@ -26,12 +26,14 @@
 #include "config.h"
 #include "CSSGradientValue.h"
 
+#include "CSSValueKeywords.h"
 #include "CSSStyleSelector.h"
 #include "GeneratedImage.h"
 #include "Gradient.h"
 #include "Image.h"
 #include "IntSize.h"
 #include "IntSizeHash.h"
+#include "NodeRenderStyle.h"
 #include "PlatformString.h"
 #include "RenderObject.h"
 
@@ -39,74 +41,13 @@ using namespace std;
 
 namespace WebCore {
 
-String CSSGradientValue::cssText() const
-{
-    String result = "-webkit-gradient(";
-    if (m_type == CSSLinearGradient)
-        result += "linear, ";
-    else
-        result += "radial, ";
-    result += m_firstX->cssText() + " ";
-    result += m_firstY->cssText() + ", ";
-    if (m_type == CSSRadialGradient)
-        result += m_firstRadius->cssText() + ", ";
-    result += m_secondX->cssText() + " ";
-    result += m_secondY->cssText();
-    if (m_type == CSSRadialGradient) {
-        result += ", ";
-        result += m_secondRadius->cssText();
-    }
-    for (unsigned i = 0; i < m_stops.size(); i++) {
-        result += ", ";
-        if (m_stops[i].m_stop == 0)
-            result += "from(" + m_stops[i].m_color->cssText() + ")";
-        else if (m_stops[i].m_stop == 1)
-            result += "to(" + m_stops[i].m_color->cssText() + ")";
-        else
-            result += "color-stop(" + String::number(m_stops[i].m_stop) + ", " + m_stops[i].m_color->cssText() + ")";
-    }
-    result += ")";
-    return result;
-}
-
-PassRefPtr<Gradient> CSSGradientValue::createGradient(RenderObject* renderer, const IntSize& size)
-{
-    ASSERT(!size.isEmpty());
-    
-    float zoomFactor = renderer->style()->effectiveZoom();
-    
-    FloatPoint firstPoint = resolvePoint(m_firstX.get(), m_firstY.get(), size, zoomFactor);
-    FloatPoint secondPoint = resolvePoint(m_secondX.get(), m_secondY.get(), size, zoomFactor);
-    
-    RefPtr<Gradient> gradient;
-    if (m_type == CSSLinearGradient)
-        gradient = Gradient::create(firstPoint, secondPoint);
-    else {
-        float firstRadius = resolveRadius(m_firstRadius.get(), zoomFactor);
-        float secondRadius = resolveRadius(m_secondRadius.get(), zoomFactor);
-        gradient = Gradient::create(firstPoint, firstRadius, secondPoint, secondRadius);
-    }
-
-    // Now add the stops.
-    sortStopsIfNeeded();
-
-    // We have to resolve colors.
-    for (unsigned i = 0; i < m_stops.size(); i++) {
-        Color color = renderer->document()->styleSelector()->getColorFromPrimitiveValue(m_stops[i].m_color.get());
-        gradient->addColorStop(m_stops[i].m_stop, color);
-    }
-
-    // The back end already sorted the stops.
-    gradient->setStopsSorted(true);
-
-    return gradient.release();
-}
-
 Image* CSSGradientValue::image(RenderObject* renderer, const IntSize& size)
 {
     ASSERT(m_clients.contains(renderer));
 
     // Need to look up our size.  Create a string of width*height to use as a hash key.
+    // FIXME: hashing based only on size is not sufficient. Color stops may use context-sensitive units (like em)
+    // that should force the color stop positions to be recomputed.
     Image* result = getImage(renderer, size);
     if (result)
         return result;
@@ -122,13 +63,18 @@ Image* CSSGradientValue::image(RenderObject* renderer, const IntSize& size)
     return result;
 }
 
+// Should only ever be called for deprecated gradients.
 static inline bool compareStops(const CSSGradientColorStop& a, const CSSGradientColorStop& b)
 {
-    return a.m_stop < b.m_stop;
+    double aVal = a.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER);
+    double bVal = b.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER);
+    
+    return aVal < bVal;
 }
 
 void CSSGradientValue::sortStopsIfNeeded()
 {
+    ASSERT(m_deprecatedType);
     if (!m_stopsSorted) {
         if (m_stops.size())
             std::stable_sort(m_stops.begin(), m_stops.end(), compareStops);
@@ -136,27 +82,394 @@ void CSSGradientValue::sortStopsIfNeeded()
     }
 }
 
-FloatPoint CSSGradientValue::resolvePoint(CSSPrimitiveValue* first, CSSPrimitiveValue* second, const IntSize& size, float zoomFactor)
+void CSSGradientValue::addStops(Gradient* gradient, RenderObject* renderer, RenderStyle* rootStyle)
+{
+    RenderStyle* style = renderer->style();
+    
+    if (m_deprecatedType) {
+        sortStopsIfNeeded();
+
+        // We have to resolve colors.
+        for (unsigned i = 0; i < m_stops.size(); i++) {
+            const CSSGradientColorStop& stop = m_stops[i];
+            Color color = renderer->document()->styleSelector()->getColorFromPrimitiveValue(stop.m_color.get());
+
+            float offset;
+            if (stop.m_position->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+                offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100;
+            else
+                offset = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_NUMBER);
+            
+            gradient->addColorStop(offset, color);
+        }
+
+        // The back end already sorted the stops.
+        gradient->setStopsSorted(true);
+        return;
+    }
+
+    size_t numStops = m_stops.size();
+    // Pair of <offset, specified>.
+    Vector<pair<float, bool> > positions(numStops);
+    
+    float gradientLength = 0;
+    bool computedGradientLength = false;
+    
+    for (size_t i = 0; i < numStops; ++i) {
+        const CSSGradientColorStop& stop = m_stops[i];
+
+        positions[i].first = 0;
+        positions[i].second = false;
+
+        if (stop.m_position) {
+            int type = stop.m_position->primitiveType();
+            if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
+                positions[i].first = stop.m_position->getFloatValue(CSSPrimitiveValue::CSS_PERCENTAGE) / 100;
+            else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
+                float length = stop.m_position->computeLengthFloat(style, rootStyle, style->effectiveZoom());
+                if (!computedGradientLength) {
+                    float xDelta = gradient->p0().x() - gradient->p1().x();
+                    float yDelta = gradient->p0().y() - gradient->p1().y();
+                    gradientLength = sqrtf(xDelta * xDelta + yDelta * yDelta);
+                }
+                positions[i].first = (gradientLength > 0) ? length / gradientLength : 0;
+            } else {
+                ASSERT_NOT_REACHED();
+                positions[i].first = 0;
+            }
+            positions[i].second = true;
+        } else {
+            // If the first color-stop does not have a position, its position defaults to 0%.
+            // If the last color-stop does not have a position, its position defaults to 100%.
+            if (!i) {
+                positions[i].first = 0;
+                positions[i].second = true;
+            } else if (numStops > 1 && i == numStops - 1) {
+                positions[i].first = 1;
+                positions[i].second = true;
+            }
+        }
+
+        // If a color-stop has a position that is less than the specified position of any
+        // color-stop before it in the list, its position is changed to be equal to the
+        // largest specified position of any color-stop before it.
+        if (positions[i].second && i > 0) {
+            size_t prevSpecifiedIndex;
+            for (prevSpecifiedIndex = i - 1; prevSpecifiedIndex; --prevSpecifiedIndex) {
+                if (positions[prevSpecifiedIndex].second)
+                    break;
+            }
+            
+            if (positions[i].first < positions[prevSpecifiedIndex].first)
+                positions[i].first = positions[prevSpecifiedIndex].first;
+        }
+    }
+
+    ASSERT(positions[0].second && positions[numStops - 1].second);
+    
+    // If any color-stop still does not have a position, then, for each run of adjacent
+    // color-stops without positions, set their positions so that they are evenly spaced
+    // between the preceding and following color-stops with positions.
+    if (numStops > 2) {
+        size_t unspecifiedRunStart = 0;
+        bool inUnspecifiedRun = false;
+
+        for (size_t i = 0; i < numStops; ++i) {
+            if (!positions[i].second && !inUnspecifiedRun) {
+                unspecifiedRunStart = i;
+                inUnspecifiedRun = true;
+            } else if (positions[i].second && inUnspecifiedRun) {
+                size_t unspecifiedRunEnd = i;
+
+                if (unspecifiedRunStart < unspecifiedRunEnd) {
+                    float lastSpecifiedOffset = positions[unspecifiedRunStart - 1].first;
+                    float nextSpecifiedOffset = positions[unspecifiedRunEnd].first;
+                    float delta = (nextSpecifiedOffset - lastSpecifiedOffset) / (unspecifiedRunEnd - unspecifiedRunStart + 1);
+                    
+                    for (size_t j = unspecifiedRunStart; j < unspecifiedRunEnd; ++j)
+                        positions[j].first = lastSpecifiedOffset + (j - unspecifiedRunStart + 1) * delta;
+                }
+
+                inUnspecifiedRun = false;
+            }
+        }
+    }
+    
+    // If the gradient goes outside the 0-1 range, normalize it by moving the endpoints, and ajusting the stops.
+    if (numStops > 1 && (positions[0].first < 0 || positions[numStops - 1].first > 1)) {
+        float firstOffset = positions[0].first;
+        float lastOffset = positions[numStops - 1].first;
+        float scale = lastOffset - firstOffset;
+        
+        for (size_t i = 0; i < numStops; ++i)
+            positions[i].first = (positions[i].first - firstOffset) / scale;
+
+        FloatPoint p0 = gradient->p0();
+        FloatPoint p1 = gradient->p1();
+        gradient->setP0(FloatPoint(p0.x() + firstOffset * (p1.x() - p0.x()), p0.y() + firstOffset * (p1.y() - p0.y())));
+        gradient->setP1(FloatPoint(p1.x() + (lastOffset - 1) * (p1.x() - p0.x()), p1.y() + (lastOffset - 1) * (p1.y() - p0.y())));
+    }
+    
+    for (unsigned i = 0; i < numStops; i++) {
+        const CSSGradientColorStop& stop = m_stops[i];
+        Color color = renderer->document()->styleSelector()->getColorFromPrimitiveValue(stop.m_color.get());
+        gradient->addColorStop(positions[i].first, color);
+    }
+
+    gradient->setStopsSorted(true);
+}
+
+static float positionFromValue(CSSPrimitiveValue* value, RenderStyle* style, RenderStyle* rootStyle, const IntSize& size, bool isHorizontal)
+{
+    float zoomFactor = style->effectiveZoom();
+
+    switch (value->primitiveType()) {
+    case CSSPrimitiveValue::CSS_NUMBER:
+        return value->getFloatValue() * zoomFactor;
+
+    case CSSPrimitiveValue::CSS_PERCENTAGE:
+        return value->getFloatValue() / 100.f * (isHorizontal ? size.width() : size.height());
+
+    case CSSPrimitiveValue::CSS_IDENT:
+        switch (value->getIdent()) {
+            case CSSValueTop:
+                ASSERT(!isHorizontal);
+                return 0;
+            case CSSValueLeft:
+                ASSERT(isHorizontal);
+                return 0;
+            case CSSValueBottom:
+                ASSERT(!isHorizontal);
+                return size.height();
+            case CSSValueRight:
+                ASSERT(isHorizontal);
+                return size.width();
+        }
+
+    default:
+        return value->computeLengthFloat(style, rootStyle, zoomFactor);
+    }
+}
+
+FloatPoint CSSGradientValue::computeEndPoint(CSSPrimitiveValue* first, CSSPrimitiveValue* second, RenderStyle* style, RenderStyle* rootStyle, const IntSize& size)
 {
     FloatPoint result;
-    if (first->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
-        result.setX(first->getFloatValue() * zoomFactor);
-    else if (first->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
-        result.setX(first->getFloatValue() / 100.f * size.width());
-    if (second->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
-        result.setY(second->getFloatValue() * zoomFactor);
-    else if (second->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
-        result.setY(second->getFloatValue() / 100.f * size.height());
 
+    if (first)
+        result.setX(positionFromValue(first, style, rootStyle, size, true));
+
+    if (second)
+        result.setY(positionFromValue(second, style, rootStyle, size, false));
+        
     return result;
 }
 
-float CSSGradientValue::resolveRadius(CSSPrimitiveValue* radius, float zoomFactor)
+String CSSLinearGradientValue::cssText() const
 {
+    String result;
+    if (m_deprecatedType) {
+        result = "-webkit-gradient(linear, ";
+        result += m_firstX->cssText() + " ";
+        result += m_firstY->cssText() + ", ";
+        result += m_secondX->cssText() + " ";
+        result += m_secondY->cssText();
+
+        for (unsigned i = 0; i < m_stops.size(); i++) {
+            const CSSGradientColorStop& stop = m_stops[i];
+            result += ", ";
+            if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 0)
+                result += "from(" + stop.m_color->cssText() + ")";
+            else if (stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 1)
+                result += "to(" + stop.m_color->cssText() + ")";
+            else
+                result += "color-stop(" + String::number(stop.m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER)) + ", " + stop.m_color->cssText() + ")";
+        }
+    } else {
+        result = "-webkit-linear-gradient(";
+        if (m_angle)
+            result += m_angle->cssText();
+        else {
+            if (m_firstX && m_firstY)
+                result += m_firstX->cssText() + " " + m_firstY->cssText();
+            else if (m_firstX || m_firstY) {
+                if (m_firstX)
+                    result += m_firstX->cssText();
+
+                if (m_firstY)
+                    result += m_firstY->cssText();
+            }
+        }
+
+        for (unsigned i = 0; i < m_stops.size(); i++) {
+            const CSSGradientColorStop& stop = m_stops[i];
+            result += ", ";
+            result += stop.m_color->cssText();
+            if (stop.m_position)
+                result += " " + stop.m_position->cssText();
+        }
+    }
+
+    result += ")";
+    return result;
+}
+
+// Compute the endpoints so that a gradient of the given angle covers a box of the given size.
+static void endPointsFromAngle(float angleDeg, const IntSize& size, FloatPoint& firstPoint, FloatPoint& secondPoint)
+{
+    angleDeg = fmodf(angleDeg, 360);
+    if (angleDeg < 0)
+        angleDeg += 360;
+    
+    if (!angleDeg) {
+        firstPoint.set(0, 0);
+        secondPoint.set(size.width(), 0);
+        return;
+    }
+    
+    if (angleDeg == 90) {
+        firstPoint.set(0, size.height());
+        secondPoint.set(0, 0);
+        return;
+    }
+
+    if (angleDeg == 180) {
+        firstPoint.set(size.width(), 0);
+        secondPoint.set(0, 0);
+        return;
+    }
+
+    float slope = tan(deg2rad(angleDeg));
+
+    // We find the endpoint by computing the intersection of the line formed by the slope,
+    // and a line perpendicular to it that intersects the corner.
+    float perpendicularSlope = -1 / slope;
+    
+    // Compute start corner relative to center.
+    float halfHeight = size.height() / 2;
+    float halfWidth = size.width() / 2;
+    FloatPoint endCorner;
+    if (angleDeg < 90)
+        endCorner.set(halfWidth, halfHeight);
+    else if (angleDeg < 180)
+        endCorner.set(-halfWidth, halfHeight);
+    else if (angleDeg < 270)
+        endCorner.set(-halfWidth, -halfHeight);
+    else
+        endCorner.set(halfWidth, -halfHeight);
+
+    // Compute c (of y = mx + c) using the corner point.
+    float c = endCorner.y() - perpendicularSlope * endCorner.x();
+    float endX = c / (slope - perpendicularSlope);
+    float endY = perpendicularSlope * endX + c;
+    
+    // We computed the end point, so set the second point, flipping the Y to account for angles going anticlockwise.
+    secondPoint.set(halfWidth + endX, size.height() - (halfHeight + endY));
+    // Reflect around the center for the start point.
+    firstPoint.set(size.width() - secondPoint.x(), size.height() - secondPoint.y());
+}
+
+PassRefPtr<Gradient> CSSLinearGradientValue::createGradient(RenderObject* renderer, const IntSize& size)
+{
+    ASSERT(!size.isEmpty());
+    
+    RenderStyle* rootStyle = renderer->document()->documentElement()->renderStyle();
+
+    FloatPoint firstPoint;
+    FloatPoint secondPoint;
+    if (m_angle) {
+        float angle = m_angle->getDoubleValue(CSSPrimitiveValue::CSS_DEG);
+        endPointsFromAngle(angle, size, firstPoint, secondPoint);
+    } else {
+        firstPoint = computeEndPoint(m_firstX.get(), m_firstY.get(), renderer->style(), rootStyle, size);
+        
+        if (m_secondX || m_secondY)
+            secondPoint = computeEndPoint(m_secondX.get(), m_secondY.get(), renderer->style(), rootStyle, size);
+        else {
+            if (m_firstX)
+                secondPoint.setX(size.width() - firstPoint.x());
+            if (m_firstY)
+                secondPoint.setY(size.height() - firstPoint.y());
+        }
+    }
+
+    RefPtr<Gradient> gradient = Gradient::create(firstPoint, secondPoint);
+
+    // Now add the stops.
+    addStops(gradient.get(), renderer, rootStyle);
+
+    return gradient.release();
+}
+
+String CSSRadialGradientValue::cssText() const
+{
+    String result;
+
+    if (m_deprecatedType)
+        result = "-webkit-gradient(radial, ";
+    else
+        result = "-webkit-radial-gradient(";
+
+    result += m_firstX->cssText() + " ";
+    result += m_firstY->cssText() + ", ";
+    result += m_firstRadius->cssText() + ", ";
+    result += m_secondX->cssText() + " ";
+    result += m_secondY->cssText();
+    result += ", ";
+    result += m_secondRadius->cssText();
+
+    for (unsigned i = 0; i < m_stops.size(); i++) {
+        result += ", ";
+        if (m_stops[i].m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 0)
+            result += "from(" + m_stops[i].m_color->cssText() + ")";
+        else if (m_stops[i].m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER) == 1)
+            result += "to(" + m_stops[i].m_color->cssText() + ")";
+        else
+            result += "color-stop(" + String::number(m_stops[i].m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER)) + ", " + m_stops[i].m_color->cssText() + ")";
+    }
+    result += ")";
+    return result;
+}
+
+float CSSRadialGradientValue::resolveRadius(CSSPrimitiveValue* radius, RenderStyle* style, RenderStyle* rootStyle)
+{
+    float zoomFactor = style->effectiveZoom();
+
     float result = 0.f;
-    if (radius->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
+    if (radius->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)  // Can the radius be a percentage?
         result = radius->getFloatValue() * zoomFactor;
+    else
+        result = radius->computeLengthFloat(style, rootStyle, zoomFactor);
+ 
     return result;
 }
 
+// FIXME: share code with the linear version
+PassRefPtr<Gradient> CSSRadialGradientValue::createGradient(RenderObject* renderer, const IntSize& size)
+{
+    ASSERT(!size.isEmpty());
+    
+    RenderStyle* rootStyle = renderer->document()->documentElement()->renderStyle();
+
+    FloatPoint firstPoint = computeEndPoint(m_firstX.get(), m_firstY.get(), renderer->style(), rootStyle, size);
+    FloatPoint secondPoint = computeEndPoint(m_secondX.get(), m_secondY.get(), renderer->style(), rootStyle, size);
+    
+    float firstRadius = resolveRadius(m_firstRadius.get(), renderer->style(), rootStyle);
+    float secondRadius = resolveRadius(m_secondRadius.get(), renderer->style(), rootStyle);
+    RefPtr<Gradient> gradient = Gradient::create(firstPoint, firstRadius, secondPoint, secondRadius);
+
+    // Now add the stops.
+    sortStopsIfNeeded();
+
+    // We have to resolve colors.
+    for (unsigned i = 0; i < m_stops.size(); i++) {
+        Color color = renderer->document()->styleSelector()->getColorFromPrimitiveValue(m_stops[i].m_color.get());
+        gradient->addColorStop(m_stops[i].m_position->getDoubleValue(CSSPrimitiveValue::CSS_NUMBER), color);
+    }
+
+    // The back end already sorted the stops.
+    gradient->setStopsSorted(true);
+
+    return gradient.release();
+}
+
 } // namespace WebCore
diff --git a/WebCore/css/CSSGradientValue.h b/WebCore/css/CSSGradientValue.h
index 83c1815..1db626a 100644
--- a/WebCore/css/CSSGradientValue.h
+++ b/WebCore/css/CSSGradientValue.h
@@ -39,72 +39,105 @@ class Gradient;
 enum CSSGradientType { CSSLinearGradient, CSSRadialGradient };
 
 struct CSSGradientColorStop {
-    CSSGradientColorStop()
-        : m_stop(0)
-    {
-    }
-    
-    float m_stop;
+    RefPtr<CSSPrimitiveValue> m_position; // percentage or length
     RefPtr<CSSPrimitiveValue> m_color;
 };
 
 class CSSGradientValue : public CSSImageGeneratorValue {
 public:
-    static PassRefPtr<CSSGradientValue> create()
-    {
-        return adoptRef(new CSSGradientValue);
-    }
-
-    virtual String cssText() const;
-
     virtual Image* image(RenderObject*, const IntSize&);
 
-    CSSGradientType type() const { return m_type; }
-    void setType(CSSGradientType type) { m_type = type; }
-    
     void setFirstX(PassRefPtr<CSSPrimitiveValue> val) { m_firstX = val; }
     void setFirstY(PassRefPtr<CSSPrimitiveValue> val) { m_firstY = val; }
     void setSecondX(PassRefPtr<CSSPrimitiveValue> val) { m_secondX = val; }
     void setSecondY(PassRefPtr<CSSPrimitiveValue> val) { m_secondY = val; }
     
-    void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
-    void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
-
     void addStop(const CSSGradientColorStop& stop) { m_stops.append(stop); }
 
+    Vector<CSSGradientColorStop>& stops() { return m_stops; }
+
     void sortStopsIfNeeded();
 
-private:
-    CSSGradientValue()
-        : m_type(CSSLinearGradient)
-        , m_stopsSorted(false)
+    bool deprecatedType() const { return m_deprecatedType; } // came from -webkit-gradient
+
+protected:
+    CSSGradientValue(bool deprecatedType = false)
+        : m_stopsSorted(false)
+        , m_deprecatedType(deprecatedType)
     {
     }
     
+    void addStops(Gradient*, RenderObject*, RenderStyle* rootStyle);
+
     // Create the gradient for a given size.
-    PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
-    
+    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&) = 0;
+
     // Resolve points/radii to front end values.
-    FloatPoint resolvePoint(CSSPrimitiveValue*, CSSPrimitiveValue*, const IntSize&, float zoomFactor);
-    float resolveRadius(CSSPrimitiveValue*, float zoomFactor);
-    
-    // Type
-    CSSGradientType m_type;
+    FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, const IntSize&);
 
-    // Points
+    // Points. Some of these may be nil for linear gradients.
     RefPtr<CSSPrimitiveValue> m_firstX;
     RefPtr<CSSPrimitiveValue> m_firstY;
     
     RefPtr<CSSPrimitiveValue> m_secondX;
     RefPtr<CSSPrimitiveValue> m_secondY;
     
-    // Radii (for radial gradients only)
-    RefPtr<CSSPrimitiveValue> m_firstRadius;
-    RefPtr<CSSPrimitiveValue> m_secondRadius;
-    
     // Stops
     Vector<CSSGradientColorStop> m_stops;
     bool m_stopsSorted;
+    bool m_deprecatedType; // -webkit-gradient()
+};
+
+
+class CSSLinearGradientValue : public CSSGradientValue {
+public:
+    static PassRefPtr<CSSLinearGradientValue> create(bool deprecatedType = false)
+    {
+        return adoptRef(new CSSLinearGradientValue(deprecatedType));
+    }
+
+    void setAngle(PassRefPtr<CSSPrimitiveValue> val) { m_angle = val; }
+
+    virtual String cssText() const;
+
+private:
+    CSSLinearGradientValue(bool deprecatedType = false)
+        : CSSGradientValue(deprecatedType)
+    {
+    }
+
+    // Create the gradient for a given size.
+    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
+
+    RefPtr<CSSPrimitiveValue> m_angle; // may be null.
+};
+
+class CSSRadialGradientValue : public CSSGradientValue {
+public:
+    static PassRefPtr<CSSRadialGradientValue> create(bool deprecatedType = false)
+    {
+        return adoptRef(new CSSRadialGradientValue(deprecatedType));
+    }
+
+    virtual String cssText() const;
+
+    void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
+    void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
+
+private:
+    CSSRadialGradientValue(bool deprecatedType = false)
+        : CSSGradientValue(deprecatedType)
+    {
+    }
+
+    // Create the gradient for a given size.
+    virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
+    
+    // Resolve points/radii to front end values.
+    float resolveRadius(CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle);
+    
+    RefPtr<CSSPrimitiveValue> m_firstRadius;
+    RefPtr<CSSPrimitiveValue> m_secondRadius;
 };
 
 } // namespace WebCore
diff --git a/WebCore/css/CSSParser.cpp b/WebCore/css/CSSParser.cpp
index 71a4ad2..441597a 100644
--- a/WebCore/css/CSSParser.cpp
+++ b/WebCore/css/CSSParser.cpp
@@ -576,7 +576,7 @@ bool CSSParser::parseValue(int propId, bool important)
     if (!m_valueList)
         return false;
 
-    CSSParserValue *value = m_valueList->current();
+    CSSParserValue* value = m_valueList->current();
 
     if (!value)
         return false;
@@ -965,8 +965,8 @@ bool CSSParser::parseValue(int propId, bool important)
                 parsedValue = CSSImageValue::create(m_styleSheet->completeURL(value->string));
                 m_valueList->next();
             }
-        } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-gradient(")) {
-            if (parseGradient(parsedValue))
+        } else if (isGeneratedImageValue(value)) {
+            if (parseGeneratedImage(parsedValue))
                 m_valueList->next();
             else
                 return false;
@@ -2362,11 +2362,8 @@ bool CSSParser::parseContent(int propId, bool important)
                 parsedValue = parseCounterContent(args, true);
                 if (!parsedValue)
                     return false;
-            } else if (equalIgnoringCase(val->function->name, "-webkit-gradient(")) {
-                if (!parseGradient(parsedValue))
-                    return false;
-            } else if (equalIgnoringCase(val->function->name, "-webkit-canvas(")) {
-                if (!parseCanvas(parsedValue))
+            } else if (isGeneratedImageValue(val)) {
+                if (!parseGeneratedImage(parsedValue))
                     return false;
             } else
                 return false;
@@ -2452,12 +2449,8 @@ bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
         return true;
     }
 
-    if (m_valueList->current()->unit == CSSParserValue::Function) {
-        if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-gradient("))
-            return parseGradient(value);
-        if (equalIgnoringCase(m_valueList->current()->function->name, "-webkit-canvas("))
-            return parseCanvas(value);
-    }
+    if (isGeneratedImageValue(m_valueList->current()))
+        return parseGeneratedImage(value);
 
     return false;
 }
@@ -4501,10 +4494,9 @@ bool CSSParser::parseBorderImage(int propId, bool important, RefPtr<CSSValue>& r
         // FIXME: The completeURL call should be done when using the CSSImageValue,
         // not when creating it.
         context.commitImage(CSSImageValue::create(m_styleSheet->completeURL(val->string)));
-    } else if (val->unit == CSSParserValue::Function) {
+    } else if (isGeneratedImageValue(val)) {
         RefPtr<CSSValue> value;
-        if ((equalIgnoringCase(val->function->name, "-webkit-gradient(") && parseGradient(value)) ||
-            (equalIgnoringCase(val->function->name, "-webkit-canvas(") && parseCanvas(value)))
+        if (parseGeneratedImage(value))
             context.commitImage(value);
         else
             return false;
@@ -4657,15 +4649,16 @@ bool CSSParser::parseCounter(int propId, int defaultValue, bool important)
     return false;
 }
 
-static PassRefPtr<CSSPrimitiveValue> parseGradientPoint(CSSParserValue* a, bool horizontal)
+// This should go away once we drop support for -webkit-gradient
+static PassRefPtr<CSSPrimitiveValue> parseDeprecatedGradientPoint(CSSParserValue* a, bool horizontal)
 {
     RefPtr<CSSPrimitiveValue> result;
     if (a->unit == CSSPrimitiveValue::CSS_IDENT) {
-        if ((equalIgnoringCase(a->string, "left") && horizontal)
-            || (equalIgnoringCase(a->string, "top") && !horizontal))
+        if ((equalIgnoringCase(a->string, "left") && horizontal) || 
+            (equalIgnoringCase(a->string, "top") && !horizontal))
             result = CSSPrimitiveValue::create(0., CSSPrimitiveValue::CSS_PERCENTAGE);
-        else if ((equalIgnoringCase(a->string, "right") && horizontal)
-                 || (equalIgnoringCase(a->string, "bottom") && !horizontal))
+        else if ((equalIgnoringCase(a->string, "right") && horizontal) ||
+                 (equalIgnoringCase(a->string, "bottom") && !horizontal))
             result = CSSPrimitiveValue::create(100., CSSPrimitiveValue::CSS_PERCENTAGE);
         else if (equalIgnoringCase(a->string, "center"))
             result = CSSPrimitiveValue::create(50., CSSPrimitiveValue::CSS_PERCENTAGE);
@@ -4674,7 +4667,7 @@ static PassRefPtr<CSSPrimitiveValue> parseGradientPoint(CSSParserValue* a, bool
     return result;
 }
 
-static bool parseGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
+static bool parseDeprecatedGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientColorStop& stop)
 {
     if (a->unit != CSSParserValue::Function)
         return false;
@@ -4688,16 +4681,16 @@ static bool parseGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientC
     if (!args)
         return false;
 
-    if (equalIgnoringCase(a->function->name, "from(")
-        || equalIgnoringCase(a->function->name, "to(")) {
+    if (equalIgnoringCase(a->function->name, "from(") || 
+        equalIgnoringCase(a->function->name, "to(")) {
         // The "from" and "to" stops expect 1 argument.
         if (args->size() != 1)
             return false;
 
         if (equalIgnoringCase(a->function->name, "from("))
-            stop.m_stop = 0.f;
+            stop.m_position = CSSPrimitiveValue::create(0, CSSPrimitiveValue::CSS_NUMBER);
         else
-            stop.m_stop = 1.f;
+            stop.m_position = CSSPrimitiveValue::create(1, CSSPrimitiveValue::CSS_NUMBER);
 
         int id = args->current()->id;
         if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
@@ -4715,9 +4708,9 @@ static bool parseGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientC
 
         CSSParserValue* stopArg = args->current();
         if (stopArg->unit == CSSPrimitiveValue::CSS_PERCENTAGE)
-            stop.m_stop = (float)stopArg->fValue / 100.f;
+            stop.m_position = CSSPrimitiveValue::create(stopArg->fValue / 100, CSSPrimitiveValue::CSS_NUMBER);
         else if (stopArg->unit == CSSPrimitiveValue::CSS_NUMBER)
-            stop.m_stop = (float)stopArg->fValue;
+            stop.m_position = CSSPrimitiveValue::create(stopArg->fValue, CSSPrimitiveValue::CSS_NUMBER);
         else
             return false;
 
@@ -4738,26 +4731,35 @@ static bool parseGradientColorStop(CSSParser* p, CSSParserValue* a, CSSGradientC
     return true;
 }
 
-bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
+bool CSSParser::parseDeprecatedGradient(RefPtr<CSSValue>& gradient)
 {
-    RefPtr<CSSGradientValue> result = CSSGradientValue::create();
-
     // Walk the arguments.
     CSSParserValueList* args = m_valueList->current()->function->args.get();
     if (!args || args->size() == 0)
         return false;
 
     // The first argument is the gradient type.  It is an identifier.
+    CSSGradientType gradientType;
     CSSParserValue* a = args->current();
     if (!a || a->unit != CSSPrimitiveValue::CSS_IDENT)
         return false;
     if (equalIgnoringCase(a->string, "linear"))
-        result->setType(CSSLinearGradient);
+        gradientType = CSSLinearGradient;
     else if (equalIgnoringCase(a->string, "radial"))
-        result->setType(CSSRadialGradient);
+        gradientType = CSSRadialGradient;
     else
         return false;
 
+    RefPtr<CSSGradientValue> result;
+    switch (gradientType) {
+        case CSSLinearGradient:
+            result = CSSLinearGradientValue::create(true);
+            break;
+        case CSSRadialGradient:
+            result = CSSRadialGradientValue::create(true);
+            break;
+    }
+
     // Comma.
     a = args->next();
     if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
@@ -4769,7 +4771,7 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
     a = args->next();
     if (!a)
         return false;
-    RefPtr<CSSPrimitiveValue> point = parseGradientPoint(a, true);
+    RefPtr<CSSPrimitiveValue> point = parseDeprecatedGradientPoint(a, true);
     if (!point)
         return false;
     result->setFirstX(point.release());
@@ -4778,7 +4780,7 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
     a = args->next();
     if (!a)
         return false;
-    point = parseGradientPoint(a, false);
+    point = parseDeprecatedGradientPoint(a, false);
     if (!point)
         return false;
     result->setFirstY(point.release());
@@ -4789,11 +4791,11 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
         return false;
 
     // For radial gradients only, we now expect a numeric radius.
-    if (result->type() == CSSRadialGradient) {
+    if (gradientType == CSSRadialGradient) {
         a = args->next();
         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
             return false;
-        result->setFirstRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
+        static_cast<CSSRadialGradientValue*>(result.get())->setFirstRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
 
         // Comma after the first radius.
         a = args->next();
@@ -4806,7 +4808,7 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
     a = args->next();
     if (!a)
         return false;
-    point = parseGradientPoint(a, true);
+    point = parseDeprecatedGradientPoint(a, true);
     if (!point)
         return false;
     result->setSecondX(point.release());
@@ -4815,13 +4817,13 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
     a = args->next();
     if (!a)
         return false;
-    point = parseGradientPoint(a, false);
+    point = parseDeprecatedGradientPoint(a, false);
     if (!point)
         return false;
     result->setSecondY(point.release());
 
     // For radial gradients only, we now expect the second radius.
-    if (result->type() == CSSRadialGradient) {
+    if (gradientType == CSSRadialGradient) {
         // Comma after the second point.
         a = args->next();
         if (!a || a->unit != CSSParserValue::Operator || a->iValue != ',')
@@ -4830,7 +4832,7 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
         a = args->next();
         if (!a || a->unit != CSSPrimitiveValue::CSS_NUMBER)
             return false;
-        result->setSecondRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
+        static_cast<CSSRadialGradientValue*>(result.get())->setSecondRadius(CSSPrimitiveValue::create(a->fValue, CSSPrimitiveValue::CSS_NUMBER));
     }
 
     // We now will accept any number of stops (0 or more).
@@ -4847,7 +4849,7 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
 
         // The function name needs to be one of "from", "to", or "color-stop."
         CSSGradientColorStop stop;
-        if (!parseGradientColorStop(this, a, stop))
+        if (!parseDeprecatedGradientColorStop(this, a, stop))
             return false;
         result->addStop(stop);
 
@@ -4859,6 +4861,172 @@ bool CSSParser::parseGradient(RefPtr<CSSValue>& gradient)
     return true;
 }
 
+static PassRefPtr<CSSPrimitiveValue> valueFromSideKeyword(CSSParserValue* a, bool& isHorizontal)
+{
+    if (a->unit != CSSPrimitiveValue::CSS_IDENT)
+        return 0;
+
+    switch (a->id) {
+        case CSSValueLeft:
+        case CSSValueRight:
+            isHorizontal = true;
+            break;
+        case CSSValueTop:
+        case CSSValueBottom:
+            isHorizontal = false;
+            break;
+        default:
+            return false;
+    }
+    return CSSPrimitiveValue::createIdentifier(a->id);
+}
+
+static PassRefPtr<CSSPrimitiveValue> parseGradientColorOrKeyword(CSSParser* p, CSSParserValue* value)
+{
+    int id = value->id;
+    if (id == CSSValueWebkitText || (id >= CSSValueAqua && id <= CSSValueWindowtext) || id == CSSValueMenu)
+        return CSSPrimitiveValue::createIdentifier(id);
+
+    return p->parseColor(value);
+}
+
+bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient)
+{
+    RefPtr<CSSLinearGradientValue> result = CSSLinearGradientValue::create();
+    
+    // Walk the arguments.
+    CSSParserValueList* args = m_valueList->current()->function->args.get();
+    if (!args || !args->size())
+        return false;
+
+    CSSParserValue* a = args->current();
+    if (!a)
+        return false;
+
+    bool expectComma = false;
+    // Look for angle.
+    if (validUnit(a, FAngle, true)) {
+        result->setAngle(CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit));
+        
+        a = args->next();
+        expectComma = true;
+    } else {
+    
+        // Look one or two optional keywords that indicate a side or corner.
+        RefPtr<CSSPrimitiveValue> startX, startY;
+        
+        RefPtr<CSSPrimitiveValue> location;
+        bool isHorizontal = false;
+        if (location = valueFromSideKeyword(a, isHorizontal)) {
+            if (isHorizontal)
+                startX = location;
+            else
+                startY = location;
+            
+            a = args->next();
+            if (a) {
+                if (location = valueFromSideKeyword(a, isHorizontal)) {
+                    if (isHorizontal) {
+                        if (startX)
+                            return false;
+                        startX = location;
+                    } else {
+                        if (startY)
+                            return false;
+                        startY = location;
+                    }
+
+                    a = args->next();
+                }
+            }
+
+            expectComma = true;
+        }
+        
+        if (!startX && !startY)
+            startY = CSSPrimitiveValue::createIdentifier(CSSValueTop);
+            
+        result->setFirstX(startX.release());
+        result->setFirstY(startY.release());
+    }
+
+    // Now look for 0 or more color stops.
+    while (a) {
+        // Look for the comma before the next stop.
+        if (expectComma) {
+            if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+                return false;
+
+            a = args->next();
+            if (!a)
+                return false;
+        }
+
+        // <color-stop> = <color> [ <percentage> | <length> ]?
+        CSSGradientColorStop stop;
+        stop.m_color = parseGradientColorOrKeyword(this, a);
+        if (!stop.m_color)
+            return false;
+
+        a = args->next();
+        if (a) {
+            if (validUnit(a, FLength | FPercent, m_strict)) {
+                stop.m_position = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes)a->unit);
+                a = args->next();
+            }
+        }
+        
+        result->addStop(stop);
+        expectComma = true;
+    }
+
+    Vector<CSSGradientColorStop>& stops = result->stops();
+    if (stops.isEmpty())
+        return false;
+
+    gradient = result.release();
+    return true;
+}
+
+bool CSSParser::parseRadialGradient(RefPtr<CSSValue>&)
+{
+    // FIXME: implement.
+    return false;
+}
+
+bool CSSParser::isGeneratedImageValue(CSSParserValue* val) const
+{
+    if (val->unit != CSSParserValue::Function)
+        return false;
+
+    return equalIgnoringCase(val->function->name, "-webkit-gradient(")
+        || equalIgnoringCase(val->function->name, "-webkit-linear-gradient(")
+        || equalIgnoringCase(val->function->name, "-webkit-radial-gradient(")
+        || equalIgnoringCase(val->function->name, "-webkit-canvas(");
+}
+
+bool CSSParser::parseGeneratedImage(RefPtr<CSSValue>& value)
+{
+    CSSParserValue* val = m_valueList->current();
+
+    if (val->unit != CSSParserValue::Function)
+        return false;
+
+    if (equalIgnoringCase(val->function->name, "-webkit-gradient("))
+        return parseDeprecatedGradient(value);
+
+    if (equalIgnoringCase(val->function->name, "-webkit-linear-gradient("))
+        return parseLinearGradient(value);
+
+    if (equalIgnoringCase(val->function->name, "-webkit-radial-gradient("))
+        return parseRadialGradient(value);
+
+    if (equalIgnoringCase(val->function->name, "-webkit-canvas("))
+        return parseCanvas(value);
+
+    return false;
+}
+
 bool CSSParser::parseCanvas(RefPtr<CSSValue>& canvas)
 {
     RefPtr<CSSCanvasValue> result = CSSCanvasValue::create();
diff --git a/WebCore/css/CSSParser.h b/WebCore/css/CSSParser.h
index eb8bb2d..2432e79 100644
--- a/WebCore/css/CSSParser.h
+++ b/WebCore/css/CSSParser.h
@@ -23,10 +23,11 @@
 #ifndef CSSParser_h
 #define CSSParser_h
 
-#include "Color.h"
+#include "CSSGradientValue.h"
 #include "CSSParserValues.h"
 #include "CSSPropertySourceData.h"
 #include "CSSSelectorList.h"
+#include "Color.h"
 #include "MediaQuery.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
@@ -155,7 +156,10 @@ namespace WebCore {
 
         // Image generators
         bool parseCanvas(RefPtr<CSSValue>&);
-        bool parseGradient(RefPtr<CSSValue>&);
+
+        bool parseDeprecatedGradient(RefPtr<CSSValue>&);
+        bool parseLinearGradient(RefPtr<CSSValue>&);
+        bool parseRadialGradient(RefPtr<CSSValue>&);
 
         PassRefPtr<CSSValueList> parseTransform();
         bool parseTransformOrigin(int propId, int& propId1, int& propId2, int& propId3, RefPtr<CSSValue>&, RefPtr<CSSValue>&, RefPtr<CSSValue>&);
@@ -264,6 +268,9 @@ namespace WebCore {
 
         void deleteFontFaceOnlyValues();
 
+        bool isGeneratedImageValue(CSSParserValue*) const;
+        bool parseGeneratedImage(RefPtr<CSSValue>&);
+
         enum SizeParameterType {
             None,
             Auto,
diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h
index 1365406..5180a9b 100644
--- a/WebCore/platform/graphics/Gradient.h
+++ b/WebCore/platform/graphics/Gradient.h
@@ -92,9 +92,13 @@ namespace WebCore {
         bool isRadial() const { return m_radial; }
         bool isZeroSize() const { return m_p0.x() == m_p1.x() && m_p0.y() == m_p1.y() && (!m_radial || m_r0 == m_r1); }
 
-#if OS(WINCE) && !PLATFORM(QT)
         const FloatPoint& p0() const { return m_p0; }
         const FloatPoint& p1() const { return m_p1; }
+
+        void setP0(const FloatPoint& p) { m_p0 = p; }
+        void setP1(const FloatPoint& p) { m_p1 = p; }
+
+#if OS(WINCE) && !PLATFORM(QT)
         float r0() const { return m_r0; }
         float r1() const { return m_r1; }
         const Vector<ColorStop, 2>& getStops() const;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list