Title: [93807] trunk
Revision
93807
Author
[email protected]
Date
2011-08-25 12:17:51 -0700 (Thu, 25 Aug 2011)

Log Message

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.

Modified Paths

Added Paths

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;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to