[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