Diff
Modified: trunk/LayoutTests/ChangeLog (93806 => 93807)
--- trunk/LayoutTests/ChangeLog 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/LayoutTests/ChangeLog 2011-08-25 19:17:51 UTC (rev 93807)
@@ -1,3 +1,23 @@
+2011-08-25 Dean Jackson <[email protected]>
+
+ https://bugs.webkit.org/show_bug.cgi?id=21586
+ Apply CSS animations and transitions to SVG properties
+
+ Reviewed by Simon Fraser.
+
+ New test for the SVG properties that can now animate. Also
+ updated the test helper script to handle colors and
+ percentages.
+
+ This test has one entry that intentionally fails for a type
+ of animation that we don't yet support: with a paint
+ server of the form "url(#invalidref) green".
+
+ * transitions/resources/transition-test-helpers.js:
+ (expected):
+ * transitions/svg-transitions-expected.txt: Added.
+ * transitions/svg-transitions.html: Added.
+
2011-08-25 Igor Oliveira <[email protected]>
[Qt] Unreviewed, rebaseline for bug 53438
Modified: trunk/LayoutTests/transitions/resources/transition-test-helpers.js (93806 => 93807)
--- trunk/LayoutTests/transitions/resources/transition-test-helpers.js 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/LayoutTests/transitions/resources/transition-test-helpers.js 2011-08-25 19:17:51 UTC (rev 93807)
@@ -52,6 +52,13 @@
return [parseInt(result[1]), parseInt(result[2])];
}
+function compareRGB(rgb, expected, tolerance)
+{
+ return (isCloseEnough(parseInt(rgb[0]), expected[0], tolerance) &&
+ isCloseEnough(parseInt(rgb[1]), expected[1], tolerance) &&
+ isCloseEnough(parseInt(rgb[2]), expected[2], tolerance));
+}
+
function checkExpectedValue(expected, index)
{
var time = expected[index][0];
@@ -81,6 +88,24 @@
break;
}
}
+ } else if (property == "fill" || property == "stroke") {
+ computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).rgbColor;
+ if (compareRGB([computedValue.red.cssText, computedValue.green.cssText, computedValue.blue.cssText], expectedValue, tolerance))
+ pass = true;
+ else {
+ // We failed. Make sure computed value is something we can read in the error message
+ computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property).cssText;
+ }
+ } else if (property == "stop-color" || property == "flood-color" || property == "lighting-color") {
+ computedValue = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
+ // The computedValue cssText is rgb(num, num, num)
+ var components = computedValue.cssText.split("(")[1].split(")")[0].split(",");
+ if (compareRGB(components, expectedValue, tolerance))
+ pass = true;
+ else {
+ // We failed. Make sure computed value is something we can read in the error message
+ computedValue = computedValue.cssText;
+ }
} else if (property == "lineHeight") {
computedValue = parseInt(window.getComputedStyle(document.getElementById(elementId)).lineHeight);
pass = isCloseEnough(computedValue, expectedValue, tolerance);
@@ -133,6 +158,10 @@
for (var i = 0; i < 4; ++i)
pass &= isCloseEnough(computedValue[i], expectedValue[i], tolerance);
break;
+ case CSSPrimitiveValue.CSS_PERCENTAGE:
+ computedValue = parseFloat(computedStyle.cssText);
+ pass = isCloseEnough(computedValue, expectedValue, tolerance);
+ break;
default:
computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
pass = isCloseEnough(computedValue, expectedValue, tolerance);
Added: trunk/LayoutTests/transitions/svg-transitions-expected.txt (0 => 93807)
--- trunk/LayoutTests/transitions/svg-transitions-expected.txt (rev 0)
+++ trunk/LayoutTests/transitions/svg-transitions-expected.txt 2011-08-25 19:17:51 UTC (rev 93807)
@@ -0,0 +1,21 @@
+CONSOLE MESSAGE: line 212: Failed to pause 'fill' transition on element 'rect7'
+Example
+PASS - "fill-opacity" property for "rect1" element at 1s saw something close to: 0.6
+PASS - "stroke-width" property for "rect1" element at 1s saw something close to: 3
+PASS - "stroke-opacity" property for "rect1" element at 1s saw something close to: 0.6
+PASS - "stroke-dashoffset" property for "rect1" element at 1s saw something close to: 5
+PASS - "fill" property for "rect2" element at 1s saw something close to: 0,127,127
+PASS - "stroke" property for "rect2" element at 1s saw something close to: 127,0,0
+PASS - "stroke-width" property for "rect4" element at 1s saw something close to: 8
+PASS - "stroke-width" property for "rect5" element at 1s saw something close to: 5
+PASS - "stroke-width" property for "rect6" element at 1s saw something close to: 15
+FAIL - "fill" property for "rect7" element at 1s expected: 0,0,127 but saw: #invalid #0000ff
+PASS - "stop-color" property for "stop1" element at 1s saw something close to: 127,127,0
+PASS - "stop-opacity" property for "stop1" element at 1s saw something close to: 0.75
+PASS - "stroke-miterlimit" property for "polyline1" element at 1s saw something close to: 11
+PASS - "kerning" property for "text1" element at 1s saw something close to: 5
+PASS - "baseline-shift" property for "text1" element at 1s saw something close to: 5
+PASS - "flood-opacity" property for "flood1" element at 1s saw something close to: 0.5
+PASS - "flood-color" property for "flood1" element at 1s saw something close to: 127,127,0
+PASS - "lighting-color" property for "light1" element at 1s saw something close to: 127,127,0
+
Property changes on: trunk/LayoutTests/transitions/svg-transitions-expected.txt
___________________________________________________________________
Added: svn:mime-type
Added: svn:keywords
Added: svn:eol-style
Added: trunk/LayoutTests/transitions/svg-transitions.html (0 => 93807)
--- trunk/LayoutTests/transitions/svg-transitions.html (rev 0)
+++ trunk/LayoutTests/transitions/svg-transitions.html 2011-08-25 19:17:51 UTC (rev 93807)
@@ -0,0 +1,185 @@
+<html>
+<head>
+ <style>
+
+ svg * {
+ -webkit-transition-property: fill, stroke, fill-opacity, stroke-opacity, stroke-width, stroke-dashoffset, stroke-miterlimit, kerning, baseline-shift, flood-color, flood-opacity, stop-color, stop-opacity, lighting-color;
+ -webkit-transition-duration: 2s;
+ -webkit-transition-timing-function: linear;
+ }
+
+ #rect1 {
+ fill: rgb(0, 0, 255);
+ stroke: red;
+ fill-opacity: 1;
+ stroke-opacity: 1;
+ stroke-width: 2;
+ stroke-dashoffset: 0;
+ stroke-dasharray: 10;
+ }
+ .animating #rect1 {
+ fill: rgb(0, 255, 0);
+ stroke: black;
+ fill-opacity: 0.2;
+ stroke-opacity: 0.2;
+ stroke-width: 4;
+ stroke-dashoffset: 10;
+ }
+
+ #rect2 {
+ fill: rgb(0, 0, 255);
+ stroke: rgb(255, 0, 0);
+ }
+ .animating #rect2 {
+ fill: rgb(0, 255, 0);
+ stroke: rgb(0, 0, 0);
+ }
+
+ #rect3 {
+ fill: url(#gradient1);
+ }
+ .animating #rect3 {
+ fill: url(#gradient2);
+ }
+
+ #stop1 {
+ stop-color: rgb(255,0,0);
+ stop-opacity: 1;
+ }
+ .animating #stop1 {
+ stop-color: rgb(0,255,0);
+ stop-opacity: 0.5;
+ }
+
+ #rect4 {
+ stroke: red;
+ stroke-width: 1px;
+ }
+ .animating #rect4 {
+ stroke-width: 4mm;
+ }
+
+ #rect5 {
+ stroke: black;
+ stroke-width: 0;
+ }
+ .animating #rect5 {
+ stroke-width: 10px;
+ }
+
+ #rect6 {
+ stroke: black;
+ stroke-width: 10%;
+ }
+ .animating #rect6 {
+ stroke-width: 20%;
+ }
+
+ #rect7 {
+ fill: url(#invalid) black;
+ }
+ .animating #rect7 {
+ fill: url(#invalid) blue;
+ }
+
+ #polyline1 {
+ fill: none;
+ stroke: black;
+ stroke-width: 4;
+ stroke-miterlimit: 12;
+ }
+ .animating #polyline1 {
+ stroke-miterlimit: 10;
+ }
+
+ #text1 {
+ kerning: 0;
+ baseline-shift: 0;
+ }
+ .animating #text1 {
+ kerning: 10px;
+ baseline-shift: 10px;
+ }
+
+ #flood1 {
+ flood-opacity: 1;
+ flood-color: rgb(255, 0, 0);
+ }
+ .animating #flood1 {
+ flood-opacity: 0;
+ flood-color: rgb(0, 255, 0);
+ }
+
+ #light1 {
+ lighting-color: rgb(255, 0, 0);
+ }
+ .animating #light1 {
+ lighting-color: rgb(0, 255, 0);
+ }
+ </style>
+ <script src=""
+ <script>
+ const expectedValues = [
+ // [time, element-id, property, expected-value, tolerance]
+ [1, "rect1", "fill-opacity", 0.6, 0.1], // 1 -> 0.2
+ [1, "rect1", "stroke-width", 3, 0.5], // 2 -> 4
+ [1, "rect1", "stroke-opacity", 0.6, 0.1], // 1 -> 0.2
+ [1, "rect1", "stroke-dashoffset", 5, 1], // 0 -> 10
+ [1, "rect2", "fill", [0, 127, 127], 20], // rgb(0, 0, 255) -> rgb(0, 255, 0)
+ [1, "rect2", "stroke", [127, 0, 0], 20], // rgb(255, 0, 0) -> rgb(0, 0, 0)
+ [1, "rect4", "stroke-width", 8, 1], // 1px to 4mm
+ [1, "rect5", "stroke-width", 5, 1], // 0 to 10px
+ [1, "rect6", "stroke-width", 15, 2], // 10% to 20%
+ [1, "rect7", "fill", [0, 0, 127], 20], // url(#invalid) black -> url(#invalid) blue
+ [1, "stop1", "stop-color", [127, 127, 0], 20], // rgb(255,0,0) -> rgb(0, 255, 0)
+ [1, "stop1", "stop-opacity", 0.75, 0.1], // 1 -> 0.5
+ [1, "polyline1", "stroke-miterlimit", 11, 0.5], // 12 -> 10 (this is an abrupt change in rendering even though the property animation is smooth)
+ [1, "text1", "kerning", 5, 1], // 0 -> 10px
+ [1, "text1", "baseline-shift", 5, 1], // 0 -> 10px
+ [1, "flood1", "flood-opacity", 0.5, 0.1], // 1 -> 0
+ [1, "flood1", "flood-color", [127, 127, 0], 20], // rgb(0, 255, 0) -> rgb(255, 0, 0)
+ [1, "light1", "lighting-color", [127, 127, 0], 20], // rgb(255, 0, 0) -> rgb(0, 255, 0)
+ ];
+
+ function setupTest()
+ {
+ document.getElementById('container').className = 'animating';
+ }
+
+ runTransitionTest(expectedValues, setupTest, usePauseAPI);
+ </script>
+</head>
+<body>
+
+<div id="container">
+ <svg viewBox="0 0 160 120" width="400px" height="300px">
+ <defs>
+ <linearGradient id="gradient1">
+ <stop id="stop1" offset="5%"/>
+ <stop offset="95%" stop-color="rgb(0,0,255)" />
+ </linearGradient>
+ <linearGradient id="gradient2">
+ <stop offset="10%" stop-color="rgb(0,255,255)" />
+ <stop offset="95%" stop-color="rgb(255, 0,255)" />
+ </linearGradient>
+ <filter id="filter1">
+ <feFlood id="flood1"/>
+ <feDiffuseLighting id="light1"/>
+ </filter>
+ </defs>
+ <rect id="rect1" x="10" y="10" width="30" height="30"/>
+ <rect id="rect2" x="90" y="10" width="30" height="30"/>
+ <rect id="rect3" x="90" y="60" width="30" height="20"/>
+ <rect id="rect4" x="10" y="100" width="10" height="10"/>
+ <rect id="rect5" x="50" y="100" width="10" height="10"/>
+ <rect id="rect6" x="90" y="100" width="10" height="10"/>
+ <rect id="rect7" x="130" y="100" width="10" height="10"/>
+ <polyline id="polyline1" points="10,70 60,75 10,80"/>
+ <text id="text1" x="100" y="60">Example</text>
+ </svg>
+</div>
+
+<div id="result"></div>
+
+</body>
+</html>
\ No newline at end of file
Property changes on: trunk/LayoutTests/transitions/svg-transitions.html
___________________________________________________________________
Added: svn:mime-type
Added: svn:keywords
Added: svn:eol-style
Modified: trunk/Source/WebCore/ChangeLog (93806 => 93807)
--- trunk/Source/WebCore/ChangeLog 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/ChangeLog 2011-08-25 19:17:51 UTC (rev 93807)
@@ -1,3 +1,71 @@
+2011-08-25 Dean Jackson <[email protected]>
+
+ https://bugs.webkit.org/show_bug.cgi?id=21586
+ Apply CSS animations and transitions to SVG properties
+
+ Reviewed by Simon Fraser.
+
+ Expose the applicable SVG properties from SVGRenderStyle to
+ RenderStyle and add them to the list of animatable
+ properties. There aren't many SVG properties that are
+ animatable directly. SVGPaint (used in "fill" and "stroke")
+ is supported only when both ends of the animation are
+ a Color. Also updated SVGLength to have some methods
+ for converting to and from user space units.
+
+ Test: transitions/svg-transitions.html
+
+ * page/animation/AnimationBase.cpp:
+ (WebCore::blendFunc):
+ Calls the blend method on SVGLength
+ (WebCore::PropertyWrapperSVGPaint::PropertyWrapperSVGPaint):
+ New property wrapper type for SVGPaint
+ (WebCore::PropertyWrapperSVGPaint::equals):
+ (WebCore::PropertyWrapperSVGPaint::blend):
+ (WebCore::AnimationBase::ensurePropertyMap):
+ * rendering/style/RenderStyle.h:
+ (WebCore::InheritedFlags::fillPaintType):
+ (WebCore::InheritedFlags::fillPaintColor):
+ (WebCore::InheritedFlags::setFillPaintColor):
+ (WebCore::InheritedFlags::strokePaintType):
+ (WebCore::InheritedFlags::strokePaintColor):
+ (WebCore::InheritedFlags::setStrokePaintColor):
+ (WebCore::InheritedFlags::strokeWidth):
+ (WebCore::InheritedFlags::setStrokeWidth):
+ (WebCore::InheritedFlags::strokeDashOffset):
+ (WebCore::InheritedFlags::setStrokeDashOffset):
+ (WebCore::InheritedFlags::strokeMiterLimit):
+ (WebCore::InheritedFlags::setStrokeMiterLimit):
+ (WebCore::InheritedFlags::stopOpacity):
+ (WebCore::InheritedFlags::setStopOpacity):
+ (WebCore::InheritedFlags::setStopColor):
+ (WebCore::InheritedFlags::setFloodColor):
+ (WebCore::InheritedFlags::setLightingColor):
+ (WebCore::InheritedFlags::baselineShiftValue):
+ (WebCore::InheritedFlags::setBaselineShiftValue):
+ (WebCore::InheritedFlags::kerning):
+ (WebCore::InheritedFlags::setKerning):
+ (WebCore::InheritedFlags::stopColor):
+ (WebCore::InheritedFlags::floodColor):
+ (WebCore::InheritedFlags::lightingColor):
+ * rendering/style/SVGRenderStyle.h:
+ (WebCore::SVGRenderStyle::stopColor):
+ (WebCore::SVGRenderStyle::floodColor):
+ (WebCore::SVGRenderStyle::lightingColor):
+ * svg/SVGLength.cpp:
+ (WebCore::SVGLength::value):
+ (WebCore::SVGLength::setValue):
+ (WebCore::SVGLength::convertValueFromUserUnits):
+ (WebCore::SVGLength::convertValueToUserUnits):
+ New conversion functions used when setting and getting values
+ * svg/SVGLength.h:
+ (WebCore::SVGLength::isZero):
+ (WebCore::SVGLength::blend):
+ Custom blend function that takes into account
+ whether the units of a length can be converted
+ in an animation, where you don't necessarily have
+ an SVGElement for context.
+
2011-08-25 Kent Tamura <[email protected]>
REGRESSION(r90971): Fix an assertion failure with textarea placeholder.
Modified: trunk/Source/WebCore/page/animation/AnimationBase.cpp (93806 => 93807)
--- trunk/Source/WebCore/page/animation/AnimationBase.cpp 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/page/animation/AnimationBase.cpp 2011-08-25 19:17:51 UTC (rev 93807)
@@ -217,6 +217,13 @@
return result;
}
+#if ENABLE(SVG)
+static inline SVGLength blendFunc(const AnimationBase*, const SVGLength& from, const SVGLength& to, double progress)
+{
+ return to.blend(from, narrowPrecisionToFloat(progress));
+}
+#endif
+
class PropertyWrapperBase;
static void addShorthandProperties();
@@ -663,7 +670,68 @@
Vector<PropertyWrapperBase*> m_propertyWrappers;
};
+#if ENABLE(SVG)
+class PropertyWrapperSVGPaint : public PropertyWrapperBase {
+public:
+ PropertyWrapperSVGPaint(int prop, const SVGPaint::SVGPaintType& (RenderStyle::*paintTypeGetter)() const, const Color& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&))
+ : PropertyWrapperBase(prop)
+ , m_paintTypeGetter(paintTypeGetter)
+ , m_getter(getter)
+ , m_setter(setter)
+ {
+ }
+ virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
+ {
+ if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)())
+ return false;
+
+ // We only support animations between SVGPaints that are pure Color values.
+ // For everything else we must return true for this method, otherwise
+ // we will try to animate between values forever.
+ if ((a->*m_paintTypeGetter)() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR) {
+ Color fromColor = (a->*m_getter)();
+ Color toColor = (b->*m_getter)();
+
+ if (!fromColor.isValid() && !toColor.isValid())
+ return true;
+
+ if (!fromColor.isValid())
+ fromColor = Color();
+ if (!toColor.isValid())
+ toColor = Color();
+
+ return fromColor == toColor;
+ }
+ return true;
+ }
+
+ virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
+ {
+ if ((a->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR
+ || (b->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR)
+ return;
+
+ Color fromColor = (a->*m_getter)();
+ Color toColor = (b->*m_getter)();
+
+ if (!fromColor.isValid() && !toColor.isValid())
+ return;
+
+ if (!fromColor.isValid())
+ fromColor = Color();
+ if (!toColor.isValid())
+ toColor = Color();
+ (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress));
+ }
+
+private:
+ const SVGPaint::SVGPaintType& (RenderStyle::*m_paintTypeGetter)() const;
+ const Color& (RenderStyle::*m_getter)() const;
+ void (RenderStyle::*m_setter)(const Color&);
+};
+#endif
+
static Vector<PropertyWrapperBase*>* gPropertyWrappers = 0;
static int gPropertyWrapperMap[numCSSProperties];
@@ -767,9 +835,25 @@
gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow));
#if ENABLE(SVG)
+ gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyFill, &RenderStyle::fillPaintType, &RenderStyle::fillPaintColor, &RenderStyle::setFillPaintColor));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity));
+
+ gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyStroke, &RenderStyle::strokePaintType, &RenderStyle::strokePaintColor, &RenderStyle::setStrokePaintColor));
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity));
+ gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth));
+ gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset));
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit));
+
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity));
- gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity));
+ gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor));
+
+ gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStopOpacity, &RenderStyle::stopOpacity, &RenderStyle::setStopOpacity));
+ gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyStopColor, &RenderStyle::stopColor, &RenderStyle::setStopColor));
+
+ gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyLightingColor, &RenderStyle::lightingColor, &RenderStyle::setLightingColor));
+
+ gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyBaselineShift, &RenderStyle::baselineShiftValue, &RenderStyle::setBaselineShiftValue));
+ gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyKerning, &RenderStyle::kerning, &RenderStyle::setKerning));
#endif
// TODO:
Modified: trunk/Source/WebCore/rendering/style/RenderStyle.h (93806 => 93807)
--- trunk/Source/WebCore/rendering/style/RenderStyle.h 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/rendering/style/RenderStyle.h 2011-08-25 19:17:51 UTC (rev 93807)
@@ -75,6 +75,7 @@
#endif
#if ENABLE(SVG)
+#include "SVGPaint.h"
#include "SVGRenderStyle.h"
#endif
@@ -1165,15 +1166,39 @@
#if ENABLE(SVG)
const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); }
SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
-
+
+ const SVGPaint::SVGPaintType& fillPaintType() const { return svgStyle()->fillPaintType(); }
+ const Color& fillPaintColor() const { return svgStyle()->fillPaintColor(); }
+ void setFillPaintColor(const Color& c) { accessSVGStyle()->setFillPaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
float fillOpacity() const { return svgStyle()->fillOpacity(); }
void setFillOpacity(float f) { accessSVGStyle()->setFillOpacity(f); }
-
+
+ const SVGPaint::SVGPaintType& strokePaintType() const { return svgStyle()->strokePaintType(); }
+ const Color& strokePaintColor() const { return svgStyle()->strokePaintColor(); }
+ void setStrokePaintColor(const Color& c) { accessSVGStyle()->setStrokePaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
float strokeOpacity() const { return svgStyle()->strokeOpacity(); }
void setStrokeOpacity(float f) { accessSVGStyle()->setStrokeOpacity(f); }
-
+ SVGLength strokeWidth() const { return svgStyle()->strokeWidth(); }
+ void setStrokeWidth(SVGLength w) { accessSVGStyle()->setStrokeWidth(w); }
+ SVGLength strokeDashOffset() const { return svgStyle()->strokeDashOffset(); }
+ void setStrokeDashOffset(SVGLength d) { accessSVGStyle()->setStrokeDashOffset(d); }
+ float strokeMiterLimit() const { return svgStyle()->strokeMiterLimit(); }
+ void setStrokeMiterLimit(float f) { accessSVGStyle()->setStrokeMiterLimit(f); }
+
float floodOpacity() const { return svgStyle()->floodOpacity(); }
void setFloodOpacity(float f) { accessSVGStyle()->setFloodOpacity(f); }
+
+ float stopOpacity() const { return svgStyle()->stopOpacity(); }
+ void setStopOpacity(float f) { accessSVGStyle()->setStopOpacity(f); }
+
+ void setStopColor(const Color& c) { accessSVGStyle()->setStopColor(c); }
+ void setFloodColor(const Color& c) { accessSVGStyle()->setFloodColor(c); }
+ void setLightingColor(const Color& c) { accessSVGStyle()->setLightingColor(c); }
+
+ SVGLength baselineShiftValue() const { return svgStyle()->baselineShiftValue(); }
+ void setBaselineShiftValue(SVGLength s) { accessSVGStyle()->setBaselineShiftValue(s); }
+ SVGLength kerning() const { return svgStyle()->kerning(); }
+ void setKerning(SVGLength k) { accessSVGStyle()->setKerning(k); }
#endif
void setWrapShape(PassRefPtr<CSSWrapShape> shape)
@@ -1412,6 +1437,12 @@
const Color colorIncludingFallback(int colorProperty) const;
+#if ENABLE(SVG)
+ const Color& stopColor() const { return svgStyle()->stopColor(); }
+ const Color& floodColor() const { return svgStyle()->floodColor(); }
+ const Color& lightingColor() const { return svgStyle()->lightingColor(); }
+#endif
+
void appendContent(PassOwnPtr<ContentData>);
};
Modified: trunk/Source/WebCore/rendering/style/SVGRenderStyle.h (93806 => 93807)
--- trunk/Source/WebCore/rendering/style/SVGRenderStyle.h 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/rendering/style/SVGRenderStyle.h 2011-08-25 19:17:51 UTC (rev 93807)
@@ -315,10 +315,10 @@
SVGLength strokeDashOffset() const { return stroke->dashOffset; }
SVGLength kerning() const { return text->kerning; }
float stopOpacity() const { return stops->opacity; }
- Color stopColor() const { return stops->color; }
+ const Color& stopColor() const { return stops->color; }
float floodOpacity() const { return misc->floodOpacity; }
- Color floodColor() const { return misc->floodColor; }
- Color lightingColor() const { return misc->lightingColor; }
+ const Color& floodColor() const { return misc->floodColor; }
+ const Color& lightingColor() const { return misc->lightingColor; }
SVGLength baselineShiftValue() const { return misc->baselineShiftValue; }
ShadowData* shadow() const { return shadowSVG->shadow.get(); }
String clipperResource() const { return resources->clipper; }
Modified: trunk/Source/WebCore/svg/SVGLength.cpp (93806 => 93807)
--- trunk/Source/WebCore/svg/SVGLength.cpp 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/svg/SVGLength.cpp 2011-08-25 19:17:51 UTC (rev 93807)
@@ -194,88 +194,86 @@
float SVGLength::value(const SVGElement* context, ExceptionCode& ec) const
{
- switch (extractType(m_unit)) {
+ return convertValueToUserUnits(m_valueInSpecifiedUnits, extractType(m_unit), context, ec);
+}
+
+void SVGLength::setValue(const SVGElement* context, float value, SVGLengthMode mode, SVGLengthType unitType, ExceptionCode& ec)
+{
+ m_unit = storeUnit(mode, unitType);
+ setValue(value, context, ec);
+}
+
+void SVGLength::setValue(float value, const SVGElement* context, ExceptionCode& ec)
+{
+ // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
+ if (extractType(m_unit) == LengthTypePercentage)
+ value = value / 100;
+
+ float convertedValue = convertValueFromUserUnits(value, extractType(m_unit), context, ec);
+ if (!ec)
+ m_valueInSpecifiedUnits = convertedValue;
+}
+
+float SVGLength::convertValueToUserUnits(float value, SVGLengthType fromUnit, const SVGElement* context, ExceptionCode& ec) const
+{
+ switch (fromUnit) {
case LengthTypeUnknown:
ec = NOT_SUPPORTED_ERR;
return 0;
case LengthTypeNumber:
- return m_valueInSpecifiedUnits;
+ return value;
+ case LengthTypePX:
+ return value;
case LengthTypePercentage:
- return convertValueFromPercentageToUserUnits(m_valueInSpecifiedUnits / 100, context, ec);
+ return convertValueFromPercentageToUserUnits(value / 100, context, ec);
case LengthTypeEMS:
- return convertValueFromEMSToUserUnits(m_valueInSpecifiedUnits, context, ec);
+ return convertValueFromEMSToUserUnits(value, context, ec);
case LengthTypeEXS:
- return convertValueFromEXSToUserUnits(m_valueInSpecifiedUnits, context, ec);
- case LengthTypePX:
- return m_valueInSpecifiedUnits;
+ return convertValueFromEXSToUserUnits(value, context, ec);
case LengthTypeCM:
- return m_valueInSpecifiedUnits / 2.54f * cssPixelsPerInch;
+ return value * cssPixelsPerInch / 2.54f;
case LengthTypeMM:
- return m_valueInSpecifiedUnits / 25.4f * cssPixelsPerInch;
+ return value * cssPixelsPerInch / 25.4f;
case LengthTypeIN:
- return m_valueInSpecifiedUnits * cssPixelsPerInch;
+ return value * cssPixelsPerInch;
case LengthTypePT:
- return m_valueInSpecifiedUnits / 72 * cssPixelsPerInch;
+ return value * cssPixelsPerInch / 72;
case LengthTypePC:
- return m_valueInSpecifiedUnits / 6 * cssPixelsPerInch;
+ return value * cssPixelsPerInch / 6;
}
-
ASSERT_NOT_REACHED();
return 0;
}
-void SVGLength::setValue(const SVGElement* context, float value, SVGLengthMode mode, SVGLengthType unitType, ExceptionCode& ec)
+float SVGLength::convertValueFromUserUnits(float value, SVGLengthType toUnit, const SVGElement* context, ExceptionCode& ec) const
{
- m_unit = storeUnit(mode, unitType);
- setValue(value, context, ec);
-}
-
-void SVGLength::setValue(float value, const SVGElement* context, ExceptionCode& ec)
-{
- switch (extractType(m_unit)) {
+ switch (toUnit) {
case LengthTypeUnknown:
ec = NOT_SUPPORTED_ERR;
- break;
+ return 0;
case LengthTypeNumber:
- m_valueInSpecifiedUnits = value;
- break;
- case LengthTypePercentage: {
- float result = convertValueFromUserUnitsToPercentage(value, context, ec);
- if (!ec)
- m_valueInSpecifiedUnits = result;
- break;
- }
- case LengthTypeEMS: {
- float result = convertValueFromUserUnitsToEMS(value, context, ec);
- if (!ec)
- m_valueInSpecifiedUnits = result;
- break;
- }
- case LengthTypeEXS: {
- float result = convertValueFromUserUnitsToEXS(value, context, ec);
- if (!ec)
- m_valueInSpecifiedUnits = result;
- break;
- }
+ return value;
+ case LengthTypePercentage:
+ return convertValueFromUserUnitsToPercentage(value * 100, context, ec);
+ case LengthTypeEMS:
+ return convertValueFromUserUnitsToEMS(value, context, ec);
+ case LengthTypeEXS:
+ return convertValueFromUserUnitsToEXS(value, context, ec);
case LengthTypePX:
- m_valueInSpecifiedUnits = value;
- break;
+ return value;
case LengthTypeCM:
- m_valueInSpecifiedUnits = value * 2.54f / cssPixelsPerInch;
- break;
+ return value * 2.54f / cssPixelsPerInch;
case LengthTypeMM:
- m_valueInSpecifiedUnits = value * 25.4f / cssPixelsPerInch;
- break;
+ return value * 25.4f / cssPixelsPerInch;
case LengthTypeIN:
- m_valueInSpecifiedUnits = value / cssPixelsPerInch;
- break;
+ return value / cssPixelsPerInch;
case LengthTypePT:
- m_valueInSpecifiedUnits = value * 72 / cssPixelsPerInch;
- break;
+ return value * 72 / cssPixelsPerInch;
case LengthTypePC:
- m_valueInSpecifiedUnits = value * 6 / cssPixelsPerInch;
- break;
+ return value * 6 / cssPixelsPerInch;
}
+ ASSERT_NOT_REACHED();
+ return 0;
}
float SVGLength::valueAsPercentage() const
Modified: trunk/Source/WebCore/svg/SVGLength.h (93806 => 93807)
--- trunk/Source/WebCore/svg/SVGLength.h 2011-08-25 19:09:12 UTC (rev 93806)
+++ trunk/Source/WebCore/svg/SVGLength.h 2011-08-25 19:17:51 UTC (rev 93807)
@@ -110,13 +110,76 @@
return type == LengthTypePercentage || type == LengthTypeEMS || type == LengthTypeEXS;
}
+ bool isZero() const
+ {
+ return !m_valueInSpecifiedUnits;
+ }
+
static SVGLength fromCSSPrimitiveValue(CSSPrimitiveValue*);
static PassRefPtr<CSSPrimitiveValue> toCSSPrimitiveValue(const SVGLength&);
static SVGLengthMode lengthModeForAnimatedLengthAttribute(const QualifiedName&);
+ SVGLength blend(const SVGLength& from, float progress) const
+ {
+ SVGLengthType toType = unitType();
+ SVGLengthType fromType = from.unitType();
+
+ if ((from.isZero() && isZero())
+ || fromType == LengthTypeUnknown
+ || toType == LengthTypeUnknown
+ || (!from.isZero() && fromType != LengthTypePercentage && toType == LengthTypePercentage)
+ || (!isZero() && fromType == LengthTypePercentage && toType != LengthTypePercentage)
+ || (!from.isZero() && !isZero() && (fromType == LengthTypeEMS || fromType == LengthTypeEXS) && fromType != toType))
+ return *this;
+
+ SVGLength length;
+ ExceptionCode ec = 0;
+
+ if (fromType == LengthTypePercentage || toType == LengthTypePercentage) {
+ float fromPercent = from.valueAsPercentage() * 100;
+ float toPercent = valueAsPercentage() * 100;
+ length.newValueSpecifiedUnits(LengthTypePercentage, fromPercent + (toPercent - fromPercent) * progress, ec);
+ if (ec)
+ return SVGLength();
+ return length;
+ }
+
+ if (fromType == toType || from.isZero() || isZero() || fromType == LengthTypeEMS || fromType == LengthTypeEXS) {
+ float fromValue = from.valueInSpecifiedUnits();
+ float toValue = valueInSpecifiedUnits();
+ if (isZero())
+ length.newValueSpecifiedUnits(fromType, fromValue + (toValue - fromValue) * progress, ec);
+ else
+ length.newValueSpecifiedUnits(toType, fromValue + (toValue - fromValue) * progress, ec);
+ if (ec)
+ return SVGLength();
+ return length;
+ }
+
+ ASSERT(!isRelative());
+ ASSERT(!from.isRelative());
+ float fromValueInUserUnits = convertValueToUserUnits(from.valueInSpecifiedUnits(), fromType, 0, ec);
+ if (ec)
+ return SVGLength();
+
+ float fromValue = convertValueFromUserUnits(fromValueInUserUnits, toType, 0, ec);
+ if (ec)
+ return SVGLength();
+
+ float toValue = valueInSpecifiedUnits();
+ length.newValueSpecifiedUnits(toType, fromValue + (toValue - fromValue) * progress, ec);
+
+ if (ec)
+ return SVGLength();
+ return length;
+ }
+
private:
bool determineViewport(const SVGElement* context, float& width, float& height) const;
+ float convertValueToUserUnits(float value, SVGLengthType fromUnit, const SVGElement* context, ExceptionCode&) const;
+ float convertValueFromUserUnits(float value, SVGLengthType toUnit, const SVGElement* context, ExceptionCode&) const;
+
float convertValueFromPercentageToUserUnits(float value, const SVGElement* context, ExceptionCode&) const;
float convertValueFromUserUnitsToPercentage(float value, const SVGElement* context, ExceptionCode&) const;