2011-01-03 Simon Fraser <simon.fraser@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 -webkit-radial-gradients.

        Tests: fast/gradients/css3-radial-gradients.html
               fast/gradients/css3-radial-gradients2.html

        * css/CSSGradientValue.cpp:
        (WebCore::blend): Used to blend colors, which is necessary when truncating
        the start of radial gradients.
        (WebCore::GradientStop): Small struct to aid gradient stop processing.
        (WebCore::CSSGradientValue::addStops): Rename 'positions' to 'stops', and store
        the color so that we can blend it when truncating radial gradients. Changed
        to handle both linear and radial gradients.
        (WebCore::CSSRadialGradientValue::cssText): Update to follow the spec.
        (WebCore::CSSRadialGradientValue::resolveRadius): Stylistic change.
        (WebCore::distanceToClosestCorner): New utility method.
        (WebCore::distanceToFarthestCorner): Ditto.
        (WebCore::CSSRadialGradientValue::createGradient): New logic to deal with shape and
        fill rules.

        * css/CSSGradientValue.h:
        (WebCore::CSSGradientValue::isLinearGradient): Color-stop processing needs to know what
        kind of gradient it's dealing with, so add new isFooGradient methods.
        (WebCore::CSSGradientValue::isRadialGradient): Ditto.
        (WebCore::CSSLinearGradientValue::isLinearGradient):
        (WebCore::CSSRadialGradientValue::setShape): New setters for shape, size etc.
        (WebCore::CSSRadialGradientValue::setSizingBehavior):
        (WebCore::CSSRadialGradientValue::setEndHorizontalSize):
        (WebCore::CSSRadialGradientValue::setEndVerticalSize):
        (WebCore::CSSRadialGradientValue::isRadialGradient):

        * css/CSSParser.h:
        * css/CSSParser.h: Pass a CSSParserValueList* into parseFillPositionXY() and parseFillPosition()
        so we can use parseFillPosition() when parsing a gradient function.
        * css/CSSParser.cpp:
        (WebCore::CSSParser::parseFillPositionXY): Pass in a CSSParserValueList*
        (WebCore::CSSParser::parseFillPosition): Ditto
        (WebCore::CSSParser::parseFillProperty): Pass m_valueList to parseFillPosition.
        (WebCore::CSSParser::parseTransformOriginShorthand): Ditto
        (WebCore::CSSParser::parseRadialGradient): Flesh out radial gradient parsing.
        (WebCore::CSSParser::parseTransformOrigin): Pass m_valueList to parseFillPosition.
        (WebCore::CSSParser::parsePerspectiveOrigin): Ditto

        * css/CSSValueKeywords.in: New keywords for radial gradient shape and fill behaviors.

        * platform/graphics/Gradient.cpp:
        (WebCore::Gradient::Gradient): Pass aspect ratio for elliptical gradients.
        * platform/graphics/Gradient.h: Add aspect ratio for elliptical gradients.
        (WebCore::Gradient::create):
        (WebCore::Gradient::startRadius): Expose radii.
        (WebCore::Gradient::endRadius):
        (WebCore::Gradient::setStartRadius): Setters are required for when we need to scale color stops.
        (WebCore::Gradient::setEndRadius):
        (WebCore::Gradient::aspectRatio):
        * platform/graphics/cg/GradientCG.cpp:
        (WebCore::Gradient::paint): For elliptical gradients, scale the CTM.
        * platform/graphics/wince/GraphicsContextWinCE.cpp:
        (WebCore::GraphicsContext::fillRect): Use start/endRadius() rather than r0() and r1().

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74915 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ff1e225b
2011-01-03 Simon Fraser <simon.fraser@apple.com>
Reviewed by David Hyatt.
Implement -webkit-linear-gradient and -webkit-radial-gradient
https://bugs.webkit.org/show_bug.cgi?id=28152
Enhance gradient parsing test for radial gradients, and add new tests
for various radial gradients.
* fast/gradients/css3-gradient-parsing-expected.txt:
* fast/gradients/css3-gradient-parsing.html:
* fast/gradients/css3-radial-gradients-expected.txt: Added.
* fast/gradients/css3-radial-gradients.html: Added.
* fast/gradients/css3-radial-gradients2-expected.txt: Added.
* fast/gradients/css3-radial-gradients2.html: Added.
* platform/mac/fast/gradients/css3-radial-gradients-expected.checksum: Added.
* platform/mac/fast/gradients/css3-radial-gradients-expected.png: Added.
* platform/mac/fast/gradients/css3-radial-gradients2-expected.checksum: Added.
* platform/mac/fast/gradients/css3-radial-gradients2-expected.png: Added.
2011-01-03 Simon Fraser <simon.fraser@apple.com>
Reviewed by David Hyatt.
......
Tests -webkit-linear-gradient and -webkit-radial-gradient
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-webkit-linear-gradient
PASS testGradient("background-image: -webkit-linear-gradient(black 0%", "background-image") is "none"
......@@ -19,6 +17,24 @@ PASS testGradient("background-image: -webkit-linear-gradient(black 10px, white 2
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%)"
-webkit-radial-gradient
PASS testGradient("background-image: -webkit-radial-gradient(white, black)", "background-image") is "-webkit-radial-gradient(center, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(bottom right, white, black)", "background-image") is "-webkit-radial-gradient(100% 100%, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(cover, white, black)", "background-image") is "-webkit-radial-gradient(center, ellipse cover, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(circle, white, black)", "background-image") is "-webkit-radial-gradient(center, circle cover, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(circle contain, white, black)", "background-image") is "-webkit-radial-gradient(center, circle contain, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(top, circle contain, white, black)", "background-image") is "-webkit-radial-gradient(50% 0%, circle contain, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(top left, circle contain, white, black)", "background-image") is "-webkit-radial-gradient(0% 0%, circle contain, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(10px 20%, circle contain, white, black)", "background-image") is "-webkit-radial-gradient(10px 20%, circle contain, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(10px, 20%, circle contain, white, black)", "background-image") is "none"
PASS testGradient("background-image: -webkit-radial-gradient(circle 10px 20%, circle contain, white, black)", "background-image") is "none"
PASS testGradient("background-image: -webkit-radial-gradient(circle 10px, circle contain, white, black)", "background-image") is "none"
PASS testGradient("background-image: -webkit-radial-gradient(center, 10px, white, black)", "background-image") is "none"
PASS testGradient("background-image: -webkit-radial-gradient(center, 10px 10px, white, black)", "background-image") is "-webkit-radial-gradient(50% 50%, 10px 10px, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(ellipse farthest-corner, white, black)", "background-image") is "-webkit-radial-gradient(center, ellipse farthest-corner, white, black)"
PASS testGradient("background-image: -webkit-radial-gradient(circle closest-side, white, black)", "background-image") is "-webkit-radial-gradient(center, circle closest-side, white, black)"
PASS successfullyParsed is true
TEST COMPLETE
......
......@@ -11,7 +11,6 @@
<script type="text/javascript">
description('Tests -webkit-linear-gradient and -webkit-radial-gradient');
function testGradient(css, queryProp)
{
......@@ -30,6 +29,8 @@ function testSame(dir, prop, altProp, value)
shouldBeEqualToString('test("' + dir + '", "' + altProp + ': ' + value + '", "' + prop + '")', value);
}
debug('<p>-webkit-linear-gradient</p>');
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"');
......@@ -47,6 +48,24 @@ shouldBe('testGradient("background-image: -webkit-linear-gradient(top left, blac
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%)"');
debug('<p>-webkit-radial-gradient</p>');
shouldBe('testGradient("background-image: -webkit-radial-gradient(white, black)", "background-image")', '"-webkit-radial-gradient(center, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(bottom right, white, black)", "background-image")', '"-webkit-radial-gradient(100% 100%, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(cover, white, black)", "background-image")', '"-webkit-radial-gradient(center, ellipse cover, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(circle, white, black)", "background-image")', '"-webkit-radial-gradient(center, circle cover, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(circle contain, white, black)", "background-image")', '"-webkit-radial-gradient(center, circle contain, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(top, circle contain, white, black)", "background-image")', '"-webkit-radial-gradient(50% 0%, circle contain, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(top left, circle contain, white, black)", "background-image")', '"-webkit-radial-gradient(0% 0%, circle contain, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(10px 20%, circle contain, white, black)", "background-image")', '"-webkit-radial-gradient(10px 20%, circle contain, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(10px, 20%, circle contain, white, black)", "background-image")', '"none"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(circle 10px 20%, circle contain, white, black)", "background-image")', '"none"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(circle 10px, circle contain, white, black)", "background-image")', '"none"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(center, 10px, white, black)", "background-image")', '"none"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(center, 10px 10px, white, black)", "background-image")', '"-webkit-radial-gradient(50% 50%, 10px 10px, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(ellipse farthest-corner, white, black)", "background-image")', '"-webkit-radial-gradient(center, ellipse farthest-corner, white, black)"');
shouldBe('testGradient("background-image: -webkit-radial-gradient(circle closest-side, white, black)", "background-image")', '"-webkit-radial-gradient(center, circle closest-side, white, black)"');
successfullyParsed = true;
</script>
......
<!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;
}
.gradient1 {
background-image: -webkit-radial-gradient(ellipse closest-corner, white, black);
background-image: -moz-radial-gradient(ellipse closest-corner, white, black);
}
.gradient2 {
background-image: -webkit-radial-gradient(50px 50%, circle closest-side, white, black);
background-image: -moz-radial-gradient(50px 50%, circle closest-side, white, black);
}
.gradient3 {
background-image: -webkit-radial-gradient(20px 50px, ellipse closest-corner, white, black);
background-image: -moz-radial-gradient(20px 50px, ellipse closest-corner, white, black);
}
.gradient4 {
background-image: -webkit-radial-gradient(20% 20%, circle closest-corner, white, black);
background-image: -moz-radial-gradient(20% 20%, circle closest-corner, white, black);
}
.gradient5 {
background-image: -webkit-radial-gradient(circle cover, red, green, blue);
background-image: -moz-radial-gradient(circle cover, red, green, blue);
}
.gradient6 {
background-image: -webkit-radial-gradient(left, circle cover, red, green 30%, blue);
background-image: -moz-radial-gradient(left, circle cover, red, green 30%, blue);
}
.gradient7 {
background-image: -webkit-radial-gradient(ellipse cover, red, green 80px, blue);
background-image: -moz-radial-gradient(ellipse cover, red, green 80px, blue);
}
.gradient8 {
background-image: -webkit-radial-gradient(circle cover, red 20%, green, blue 150%);
background-image: -moz-radial-gradient(circle cover, red 20%, green, blue 150%);
}
.gradient9 {
background-image: -webkit-radial-gradient(20% 20%, circle closest-corner, red -50%, green, blue 150%);
background-image: -moz-radial-gradient(20% 20%, circle closest-corner, red -50%, green, blue 150%);
}
</style>
<script type="text/javascript" charset="utf-8">
if (window.layoutTestController) {
var dumpPixels = true;
layoutTestController.dumpAsText(dumpPixels);
}
</script>
</head>
<body>
<div class="gradient1 box"></div>
<div class="gradient2 box"></div>
<div class="gradient3 box"></div>
<br>
<div class="gradient4 box"></div>
<div class="gradient5 box"></div>
<div class="gradient6 box"></div>
<br>
<div class="gradient7 box"></div>
<div class="gradient8 box"></div>
<div class="gradient9 box"></div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style type="text/css" media="screen">
.box {
display: inline-block;
height: 250px;
width: 200px;
margin: 10px;
border: 1px solid black;
background-repeat: no-repeat;
}
.gradient1 {
/* Green should coincide with the edge of the box, with blue fill (buggy in CG). */
background-image: -webkit-radial-gradient(left, circle closest-corner, red, green 150px, blue);
background-image: -moz-radial-gradient(left, circle closest-corner, red, green 150px, blue);
}
.gradient2 {
/* Fill should be orange (buggy in CG). */
background-image: -webkit-radial-gradient(left, circle closest-corner, red, green 150px, blue, orange 101%);
background-image: -moz-radial-gradient(left, circle closest-corner, red, green 150px, blue, orange 101%);
}
.gradient3 {
background-image: -webkit-radial-gradient(-100px center, ellipse farthest-corner, black, white);
background-image: -moz-radial-gradient(-100px center, ellipse farthest-corner, black, white);
}
.gradient4 {
background-image: -webkit-radial-gradient(-100px center, ellipse closest-corner, black, white);
background-image: -moz-radial-gradient(-100px center, ellipse closest-corner, black, white);
}
.gradient5 {
background-image: -webkit-radial-gradient(bottom right, black, white);
background-image: -moz-radial-gradient(bottom right, black, white);
}
.gradient6 {
background-image: -webkit-radial-gradient(50% 20%, ellipse contain, black, white);
background-image: -moz-radial-gradient(50% 20%, ellipse contain, black, white);
}
</style>
<script type="text/javascript" charset="utf-8">
if (window.layoutTestController) {
var dumpPixels = true;
layoutTestController.dumpAsText(dumpPixels);
}
</script>
</head>
<body>
<div class="gradient1 box"></div>
<div class="gradient2 box"></div>
<div class="gradient3 box"></div>
<br>
<div class="gradient4 box"></div>
<div class="gradient5 box"></div>
<div class="gradient6 box"></div>
</body>
</html>
af88d9c4da4d2856797d2ab20f7f2927
\ No newline at end of file
63d36fd71d88bb4bbe7ae42f8ce2f873
\ No newline at end of file
......@@ -9,6 +9,71 @@
(WebCore::RenderTableCell::RenderTableCell): Removed initialization of m_percentageHeight.
* rendering/RenderTableCell.h: Removed m_percentageHeight.
2011-01-03 Simon Fraser <simon.fraser@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 -webkit-radial-gradients.
Tests: fast/gradients/css3-radial-gradients.html
fast/gradients/css3-radial-gradients2.html
* css/CSSGradientValue.cpp:
(WebCore::blend): Used to blend colors, which is necessary when truncating
the start of radial gradients.
(WebCore::GradientStop): Small struct to aid gradient stop processing.
(WebCore::CSSGradientValue::addStops): Rename 'positions' to 'stops', and store
the color so that we can blend it when truncating radial gradients. Changed
to handle both linear and radial gradients.
(WebCore::CSSRadialGradientValue::cssText): Update to follow the spec.
(WebCore::CSSRadialGradientValue::resolveRadius): Stylistic change.
(WebCore::distanceToClosestCorner): New utility method.
(WebCore::distanceToFarthestCorner): Ditto.
(WebCore::CSSRadialGradientValue::createGradient): New logic to deal with shape and
fill rules.
* css/CSSGradientValue.h:
(WebCore::CSSGradientValue::isLinearGradient): Color-stop processing needs to know what
kind of gradient it's dealing with, so add new isFooGradient methods.
(WebCore::CSSGradientValue::isRadialGradient): Ditto.
(WebCore::CSSLinearGradientValue::isLinearGradient):
(WebCore::CSSRadialGradientValue::setShape): New setters for shape, size etc.
(WebCore::CSSRadialGradientValue::setSizingBehavior):
(WebCore::CSSRadialGradientValue::setEndHorizontalSize):
(WebCore::CSSRadialGradientValue::setEndVerticalSize):
(WebCore::CSSRadialGradientValue::isRadialGradient):
* css/CSSParser.h:
* css/CSSParser.h: Pass a CSSParserValueList* into parseFillPositionXY() and parseFillPosition()
so we can use parseFillPosition() when parsing a gradient function.
* css/CSSParser.cpp:
(WebCore::CSSParser::parseFillPositionXY): Pass in a CSSParserValueList*
(WebCore::CSSParser::parseFillPosition): Ditto
(WebCore::CSSParser::parseFillProperty): Pass m_valueList to parseFillPosition.
(WebCore::CSSParser::parseTransformOriginShorthand): Ditto
(WebCore::CSSParser::parseRadialGradient): Flesh out radial gradient parsing.
(WebCore::CSSParser::parseTransformOrigin): Pass m_valueList to parseFillPosition.
(WebCore::CSSParser::parsePerspectiveOrigin): Ditto
* css/CSSValueKeywords.in: New keywords for radial gradient shape and fill behaviors.
* platform/graphics/Gradient.cpp:
(WebCore::Gradient::Gradient): Pass aspect ratio for elliptical gradients.
* platform/graphics/Gradient.h: Add aspect ratio for elliptical gradients.
(WebCore::Gradient::create):
(WebCore::Gradient::startRadius): Expose radii.
(WebCore::Gradient::endRadius):
(WebCore::Gradient::setStartRadius): Setters are required for when we need to scale color stops.
(WebCore::Gradient::setEndRadius):
(WebCore::Gradient::aspectRatio):
* platform/graphics/cg/GradientCG.cpp:
(WebCore::Gradient::paint): For elliptical gradients, scale the CTM.
* platform/graphics/wince/GraphicsContextWinCE.cpp:
(WebCore::GraphicsContext::fillRect): Use start/endRadius() rather than r0() and r1().
2011-01-03 Simon Fraser <simon.fraser@apple.com>
Reviewed by David Hyatt.
......
This diff is collapsed.
......@@ -57,6 +57,9 @@ public:
Vector<CSSGradientColorStop>& stops() { return m_stops; }
void sortStopsIfNeeded();
virtual bool isLinearGradient() const { return false; }
virtual bool isRadialGradient() const { return false; }
bool deprecatedType() const { return m_deprecatedType; } // came from -webkit-gradient
......@@ -75,7 +78,7 @@ protected:
// Resolve points/radii to front end values.
FloatPoint computeEndPoint(CSSPrimitiveValue*, CSSPrimitiveValue*, RenderStyle*, RenderStyle* rootStyle, const IntSize&);
// Points. Some of these may be nil for linear gradients.
// Points. Some of these may be null for linear gradients.
RefPtr<CSSPrimitiveValue> m_firstX;
RefPtr<CSSPrimitiveValue> m_firstY;
......@@ -106,6 +109,8 @@ private:
{
}
virtual bool isLinearGradient() const { return true; }
// Create the gradient for a given size.
virtual PassRefPtr<Gradient> createGradient(RenderObject*, const IntSize&);
......@@ -124,20 +129,36 @@ public:
void setFirstRadius(PassRefPtr<CSSPrimitiveValue> val) { m_firstRadius = val; }
void setSecondRadius(PassRefPtr<CSSPrimitiveValue> val) { m_secondRadius = val; }
void setShape(PassRefPtr<CSSPrimitiveValue> val) { m_shape = val; }
void setSizingBehavior(PassRefPtr<CSSPrimitiveValue> val) { m_sizingBehavior = val; }
void setEndHorizontalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endHorizontalSize = val; }
void setEndVerticalSize(PassRefPtr<CSSPrimitiveValue> val) { m_endVerticalSize = val; }
private:
CSSRadialGradientValue(bool deprecatedType = false)
: CSSGradientValue(deprecatedType)
{
}
virtual bool isRadialGradient() const { return true; }
// 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);
// These may be null for non-deprecated gradients.
RefPtr<CSSPrimitiveValue> m_firstRadius;
RefPtr<CSSPrimitiveValue> m_secondRadius;
// The below are only used for non-deprecated gradients.
RefPtr<CSSPrimitiveValue> m_shape;
RefPtr<CSSPrimitiveValue> m_sizingBehavior;
RefPtr<CSSPrimitiveValue> m_endHorizontalSize;
RefPtr<CSSPrimitiveValue> m_endVerticalSize;
};
} // namespace WebCore
......
......@@ -2455,9 +2455,9 @@ bool CSSParser::parseFillImage(RefPtr<CSSValue>& value)
return false;
}
PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(bool& xFound, bool& yFound)
PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(CSSParserValueList* valueList, bool& xFound, bool& yFound)
{
int id = m_valueList->current()->id;
int id = valueList->current()->id;
if (id == CSSValueLeft || id == CSSValueTop || id == CSSValueRight || id == CSSValueBottom || id == CSSValueCenter) {
int percent = 0;
if (id == CSSValueLeft || id == CSSValueRight) {
......@@ -2479,27 +2479,27 @@ PassRefPtr<CSSValue> CSSParser::parseFillPositionXY(bool& xFound, bool& yFound)
percent = 50;
return CSSPrimitiveValue::create(percent, CSSPrimitiveValue::CSS_PERCENTAGE);
}
if (validUnit(m_valueList->current(), FPercent | FLength, m_strict))
return CSSPrimitiveValue::create(m_valueList->current()->fValue,
(CSSPrimitiveValue::UnitTypes)m_valueList->current()->unit);
if (validUnit(valueList->current(), FPercent | FLength, m_strict))
return CSSPrimitiveValue::create(valueList->current()->fValue,
(CSSPrimitiveValue::UnitTypes)valueList->current()->unit);
return 0;
}
void CSSParser::parseFillPosition(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
void CSSParser::parseFillPosition(CSSParserValueList* valueList, RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2)
{
CSSParserValue* value = m_valueList->current();
CSSParserValue* value = valueList->current();
// Parse the first value. We're just making sure that it is one of the valid keywords or a percentage/length.
bool value1IsX = false, value1IsY = false;
value1 = parseFillPositionXY(value1IsX, value1IsY);
value1 = parseFillPositionXY(valueList, value1IsX, value1IsY);
if (!value1)
return;
// It only takes one value for background-position to be correctly parsed if it was specified in a shorthand (since we
// can assume that any other values belong to the rest of the shorthand). If we're not parsing a shorthand, though, the
// value was explicitly specified for our property.
value = m_valueList->next();
value = valueList->next();
// First check for the comma. If so, we are finished parsing this value or value pair.
if (value && value->unit == CSSParserValue::Operator && value->iValue == ',')
......@@ -2507,9 +2507,9 @@ void CSSParser::parseFillPosition(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& va
bool value2IsX = false, value2IsY = false;
if (value) {
value2 = parseFillPositionXY(value2IsX, value2IsY);
value2 = parseFillPositionXY(valueList, value2IsX, value2IsY);
if (value2)
m_valueList->next();
valueList->next();
else {
if (!inShorthand()) {
value1.clear();
......@@ -2698,13 +2698,13 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
break;
case CSSPropertyBackgroundPosition:
case CSSPropertyWebkitMaskPosition:
parseFillPosition(currValue, currValue2);
parseFillPosition(m_valueList, currValue, currValue2);
// parseFillPosition advances the m_valueList pointer
break;
case CSSPropertyBackgroundPositionX:
case CSSPropertyWebkitMaskPositionX: {
bool xFound = false, yFound = true;
currValue = parseFillPositionXY(xFound, yFound);
currValue = parseFillPositionXY(m_valueList, xFound, yFound);
if (currValue)
m_valueList->next();
break;
......@@ -2712,7 +2712,7 @@ bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
case CSSPropertyBackgroundPositionY:
case CSSPropertyWebkitMaskPositionY: {
bool xFound = true, yFound = false;
currValue = parseFillPositionXY(xFound, yFound);
currValue = parseFillPositionXY(m_valueList, xFound, yFound);
if (currValue)
m_valueList->next();
break;
......@@ -2863,7 +2863,7 @@ PassRefPtr<CSSValue> CSSParser::parseAnimationProperty()
bool CSSParser::parseTransformOriginShorthand(RefPtr<CSSValue>& value1, RefPtr<CSSValue>& value2, RefPtr<CSSValue>& value3)
{
parseFillPosition(value1, value2);
parseFillPosition(m_valueList, value1, value2);
// now get z
if (m_valueList->current()) {
......@@ -4988,10 +4988,152 @@ bool CSSParser::parseLinearGradient(RefPtr<CSSValue>& gradient)
return true;
}
bool CSSParser::parseRadialGradient(RefPtr<CSSValue>&)
bool CSSParser::parseRadialGradient(RefPtr<CSSValue>& gradient)
{
// FIXME: implement.
return false;
RefPtr<CSSRadialGradientValue> result = CSSRadialGradientValue::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;
// Optional background-position
RefPtr<CSSValue> centerX;
RefPtr<CSSValue> centerY;
// parseFillPosition advances the args next pointer.
parseFillPosition(args, centerX, centerY);
a = args->current();
if (centerX || centerY) {
// Comma
if (a->unit != CSSParserValue::Operator || a->iValue != ',')
return false;
a = args->next();
if (!a)
return false;
}
ASSERT(!centerX || centerX->isPrimitiveValue());
ASSERT(!centerY || centerY->isPrimitiveValue());
result->setFirstX(static_cast<CSSPrimitiveValue*>(centerX.get()));
result->setSecondX(static_cast<CSSPrimitiveValue*>(centerX.get()));
// CSS3 radial gradients always share the same start and end point.
result->setFirstY(static_cast<CSSPrimitiveValue*>(centerY.get()));
result->setSecondY(static_cast<CSSPrimitiveValue*>(centerY.get()));
RefPtr<CSSPrimitiveValue> shapeValue;
RefPtr<CSSPrimitiveValue> sizeValue;
// Optional shape and/or size in any order.
for (int i = 0; i < 2; ++i) {
if (a->unit != CSSPrimitiveValue::CSS_IDENT)
break;
bool foundValue = false;
switch (a->id) {
case CSSValueCircle:
case CSSValueEllipse:
shapeValue = CSSPrimitiveValue::createIdentifier(a->id);
foundValue = true;
break;
case CSSValueClosestSide:
case CSSValueClosestCorner:
case CSSValueFarthestSide:
case CSSValueFarthestCorner:
case CSSValueContain:
case CSSValueCover:
sizeValue = CSSPrimitiveValue::createIdentifier(a->id);
foundValue = true;
break;
}
if (foundValue) {
a = args->next();
if (!a)
return false;
expectComma = true;
}
}
result->setShape(shapeValue);
result->setSizingBehavior(sizeValue);
// Or, two lengths or percentages
RefPtr<CSSPrimitiveValue> horizontalSize;
RefPtr<CSSPrimitiveValue> verticalSize;
if (!shapeValue && !sizeValue) {
if (validUnit(a, FLength | FPercent, m_strict)) {
horizontalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
a = args->next();
if (!a)
return false;
expectComma = true;
}
if (validUnit(a, FLength | FPercent, m_strict)) {
verticalSize = CSSPrimitiveValue::create(a->fValue, (CSSPrimitiveValue::UnitTypes) a->unit);
a = args->next();
if (!a)
return false;
expectComma = true;
}
}
// Must have neither or both.
if (!horizontalSize != !verticalSize)
return false;
result->setEndHorizontalSize(horizontalSize);
result->setEndVerticalSize(verticalSize);
// 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 != ',')