2011-02-20 Dirk Schulze <krit@webkit.org>
authorkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 20 Feb 2011 22:27:58 +0000 (22:27 +0000)
committerkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 20 Feb 2011 22:27:58 +0000 (22:27 +0000)
        Reviewed by Nikolas Zimmermann.

        SVG animation - analyze attribute type for animation
        https://bugs.webkit.org/show_bug.cgi?id=54542

        Check dynamic update of attributeName. The test fails at the moment, because of some wrong
        internal mapping. Tested update manually with gdb. Working on a fix to get this test pass
        as well.

        * svg/animations/animate-dynamic-update-attributeName-expected.txt: Added.
        * svg/animations/animate-dynamic-update-attributeName.html: Added.
        * svg/animations/script-tests/animate-dynamic-update-attributeName.js: Added.
        (sample1):
        (sample2):
        (sample3):
        (executeTest):
2011-02-20  Dirk Schulze  <krit@webkit.org>

        Reviewed by Nikolas Zimmermann.

        SVG animation - analyze attribute type for animation
        https://bugs.webkit.org/show_bug.cgi?id=54542

        Analyze animated attribute type to determine the kind of animation. Removed enum PropertyType and replace it
        with AnimatedAttributeType instead. More cleanup of the animation code.
        Added missing fillAttributeToPropertyTypeMap() for SVGGElement.

        Use QualifiedName instead of AtomicStrings for attribute names. This makes it easier to handle animated attributes
        from a different namespace like xlink:href. The rest of the SVG code is using QualifiedNames as well.

        No change of functionality on the animation code. The changes for the <g>-element affect animateTransform. Sadly
        animateTransform is not supported by our SVG animation test script at the moment. Can still be tested manually
        with the W3C test suite in trunk.

        The change on SVGUseElement gets covered by animate-elem-39-t.svg

        Test: svg/animations/animate-dynamic-update-attributeName.html

        * svg/SVGAnimateElement.cpp:
        (WebCore::SVGAnimateElement::SVGAnimateElement):
        (WebCore::SVGAnimateElement::hasValidAttributeType):
        (WebCore::SVGAnimateElement::determineAnimatedAttributeType):
        (WebCore::SVGAnimateElement::calculateAnimatedValue):
        (WebCore::inheritsFromProperty):
        (WebCore::SVGAnimateElement::calculateFromAndToValues):
        (WebCore::SVGAnimateElement::calculateFromAndByValues):
        (WebCore::SVGAnimateElement::resetToBaseValue):
        (WebCore::SVGAnimateElement::applyResultsToTarget):
        (WebCore::SVGAnimateElement::calculateDistance):
        * svg/SVGAnimateElement.h:
        * svg/SVGAnimateMotionElement.cpp:
        (WebCore::SVGAnimateMotionElement::hasValidAttributeType):
        (WebCore::parsePoint):
        (WebCore::SVGAnimateMotionElement::resetToBaseValue):
        (WebCore::SVGAnimateMotionElement::calculateAnimatedValue):
        (WebCore::SVGAnimateMotionElement::calculateDistance):
        * svg/SVGAnimateMotionElement.h:
        * svg/SVGAnimateTransformElement.cpp:
        (WebCore::SVGAnimateTransformElement::hasValidAttributeType):
        (WebCore::SVGAnimateTransformElement::determineAnimatedAttributeType):
        (WebCore::SVGAnimateTransformElement::resetToBaseValue):
        (WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
        (WebCore::SVGAnimateTransformElement::calculateFromAndByValues):
        (WebCore::SVGAnimateTransformElement::applyResultsToTarget):
        (WebCore::SVGAnimateTransformElement::calculateDistance):
        * svg/SVGAnimateTransformElement.h:
        * svg/SVGAnimationElement.cpp:
        (WebCore::parseKeyTimes):
        (WebCore::parseKeySplines):
        (WebCore::SVGAnimationElement::isTargetAttributeCSSProperty):
        (WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue):
        (WebCore::SVGAnimationElement::calculateKeyTimesForCalcModePaced):
        (WebCore::solveEpsilon):
        (WebCore::SVGAnimationElement::calculatePercentFromKeyPoints):
        (WebCore::SVGAnimationElement::currentValuesFromKeyPoints):
        (WebCore::SVGAnimationElement::currentValuesForValuesAnimation):
        (WebCore::SVGAnimationElement::startedActiveInterval):
        * svg/SVGAnimationElement.h:
        * svg/SVGFilterElement.cpp:
        (WebCore::SVGFilterElement::fillAttributeToPropertyTypeMap):
        * svg/SVGGElement.cpp:
        (WebCore::SVGGElement::attributeToPropertyTypeMap):
        (WebCore::SVGGElement::fillAttributeToPropertyTypeMap): Added to fill the animated attribute map for this element.
        * svg/SVGGElement.h:
        * svg/SVGUseElement.cpp:
        (WebCore::SVGUseElement::fillAttributeToPropertyTypeMap): Changed attribute type to AnimatedString for xlink:href.
        * svg/animation/SMILTimeContainer.cpp:
        (WebCore::SMILTimeContainer::baseValueFor):
        (WebCore::SMILTimeContainer::updateAnimations):
        * svg/animation/SMILTimeContainer.h:
        * svg/animation/SVGSMILElement.cpp:
        (WebCore::SVGSMILElement::SVGSMILElement):
        (WebCore::constructQualifiedName): Create a QualifiedName from a attribute name.
        (WebCore::SVGSMILElement::insertedIntoDocument): Update local varaible of attribute name.
        (WebCore::SVGSMILElement::removedFromDocument): Ditto.
        (WebCore::SVGSMILElement::attributeChanged): Ditto.
        * svg/animation/SVGSMILElement.h:
        (WebCore::SVGSMILElement::attributeName):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@79155 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
LayoutTests/ChangeLog
LayoutTests/svg/animations/animate-dynamic-update-attributeName-expected.txt [new file with mode: 0644]
LayoutTests/svg/animations/animate-dynamic-update-attributeName.html [new file with mode: 0644]
LayoutTests/svg/animations/script-tests/animate-dynamic-update-attributeName.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/svg/SVGAnimateElement.cpp
Source/WebCore/svg/SVGAnimateElement.h
Source/WebCore/svg/SVGAnimateMotionElement.cpp
Source/WebCore/svg/SVGAnimateMotionElement.h
Source/WebCore/svg/SVGAnimateTransformElement.cpp
Source/WebCore/svg/SVGAnimateTransformElement.h
Source/WebCore/svg/SVGAnimationElement.cpp
Source/WebCore/svg/SVGAnimationElement.h
Source/WebCore/svg/SVGFilterElement.cpp
Source/WebCore/svg/SVGGElement.cpp
Source/WebCore/svg/SVGGElement.h
Source/WebCore/svg/SVGUseElement.cpp
Source/WebCore/svg/animation/SMILTimeContainer.cpp
Source/WebCore/svg/animation/SMILTimeContainer.h
Source/WebCore/svg/animation/SVGSMILElement.cpp
Source/WebCore/svg/animation/SVGSMILElement.h

index 49be0a3..0720e7e 100644 (file)
@@ -1,3 +1,22 @@
+2011-02-20  Dirk Schulze  <krit@webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation - analyze attribute type for animation
+        https://bugs.webkit.org/show_bug.cgi?id=54542
+
+        Check dynamic update of attributeName. The test fails at the moment, because of some wrong
+        internal mapping. Tested update manually with gdb. Working on a fix to get this test pass
+        as well.
+
+        * svg/animations/animate-dynamic-update-attributeName-expected.txt: Added.
+        * svg/animations/animate-dynamic-update-attributeName.html: Added.
+        * svg/animations/script-tests/animate-dynamic-update-attributeName.js: Added.
+        (sample1):
+        (sample2):
+        (sample3):
+        (executeTest):
+
 2011-02-19  Zan Dobersek  <zandobersek@gmail.com>
 
         Reviewed by Martin Robinson.
diff --git a/LayoutTests/svg/animations/animate-dynamic-update-attributeName-expected.txt b/LayoutTests/svg/animations/animate-dynamic-update-attributeName-expected.txt
new file mode 100644 (file)
index 0000000..ef7fde3
--- /dev/null
@@ -0,0 +1,13 @@
+SVG 1.1 dynamic animation tests
+
+Test behavior on dynamic-update of attributeName
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS rect.style.color is 'rgb(0, 128, 0)'
+FAIL rect.style.fill should be #008000. Was #FF0000.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/animations/animate-dynamic-update-attributeName.html b/LayoutTests/svg/animations/animate-dynamic-update-attributeName.html
new file mode 100644 (file)
index 0000000..60755fa
--- /dev/null
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script src="../dynamic-updates/resources/SVGTestCase.js"></script>
+<script src="resources/SVGAnimationTestCase.js"></script>
+</head>
+<body>
+<h1>SVG 1.1 dynamic animation tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/animate-dynamic-update-attributeName.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/svg/animations/script-tests/animate-dynamic-update-attributeName.js b/LayoutTests/svg/animations/script-tests/animate-dynamic-update-attributeName.js
new file mode 100644 (file)
index 0000000..5bfe856
--- /dev/null
@@ -0,0 +1,52 @@
+description("Test behavior on dynamic-update of attributeName");
+createSVGTestCase();
+
+// Setup test document
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "200");
+rect.setAttribute("height", "200");
+rect.setAttribute("fill", "red");
+rect.setAttribute("color", "red");
+rect.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "color");
+animate.setAttribute("from", "green");
+animate.setAttribute("to", "green");
+animate.setAttribute("begin", "click");
+animate.setAttribute("dur", "3s");
+animate.setAttribute("fill", "freeze");
+animate.setAttribute("calcMode", "discrete");
+rect.appendChild(animate);
+rootSVGElement.appendChild(rect);
+
+// Setup animation test
+function sample1() {
+    shouldBe("rect.style.color", "'rgb(0, 128, 0)'");
+}
+
+function sample2() {
+    // Set 'attributeName' from 'color' to 'fill'
+    animate.setAttribute("attributeName", "fill");
+}
+
+function sample3() {
+    shouldBe("rect.style.fill", "'#008000'");
+}
+
+function executeTest() {
+    const expectedValues = [
+        // [animationId, time, elementId, sampleCallback]
+        ["animation", 0.1,    "rect", sample1],
+        ["animation", 1.5,    "rect", sample2],
+        ["animation", 3.0,    "rect", sample3],
+    ];
+
+    runAnimationTest(expectedValues);
+}
+
+// Begin test async
+window.setTimeout("triggerUpdate(50, 50)", 0);
+var successfullyParsed = true;
index 145e447..27ccf18 100644 (file)
@@ -1,3 +1,86 @@
+2011-02-20  Dirk Schulze  <krit@webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVG animation - analyze attribute type for animation
+        https://bugs.webkit.org/show_bug.cgi?id=54542
+
+        Analyze animated attribute type to determine the kind of animation. Removed enum PropertyType and replace it
+        with AnimatedAttributeType instead. More cleanup of the animation code.
+        Added missing fillAttributeToPropertyTypeMap() for SVGGElement.
+
+        Use QualifiedName instead of AtomicStrings for attribute names. This makes it easier to handle animated attributes
+        from a different namespace like xlink:href. The rest of the SVG code is using QualifiedNames as well.
+
+        No change of functionality on the animation code. The changes for the <g>-element affect animateTransform. Sadly
+        animateTransform is not supported by our SVG animation test script at the moment. Can still be tested manually
+        with the W3C test suite in trunk.
+
+        The change on SVGUseElement gets covered by animate-elem-39-t.svg
+
+        Test: svg/animations/animate-dynamic-update-attributeName.html
+
+        * svg/SVGAnimateElement.cpp:
+        (WebCore::SVGAnimateElement::SVGAnimateElement):
+        (WebCore::SVGAnimateElement::hasValidAttributeType):
+        (WebCore::SVGAnimateElement::determineAnimatedAttributeType):
+        (WebCore::SVGAnimateElement::calculateAnimatedValue):
+        (WebCore::inheritsFromProperty):
+        (WebCore::SVGAnimateElement::calculateFromAndToValues):
+        (WebCore::SVGAnimateElement::calculateFromAndByValues):
+        (WebCore::SVGAnimateElement::resetToBaseValue):
+        (WebCore::SVGAnimateElement::applyResultsToTarget):
+        (WebCore::SVGAnimateElement::calculateDistance):
+        * svg/SVGAnimateElement.h:
+        * svg/SVGAnimateMotionElement.cpp:
+        (WebCore::SVGAnimateMotionElement::hasValidAttributeType):
+        (WebCore::parsePoint):
+        (WebCore::SVGAnimateMotionElement::resetToBaseValue):
+        (WebCore::SVGAnimateMotionElement::calculateAnimatedValue):
+        (WebCore::SVGAnimateMotionElement::calculateDistance):
+        * svg/SVGAnimateMotionElement.h:
+        * svg/SVGAnimateTransformElement.cpp:
+        (WebCore::SVGAnimateTransformElement::hasValidAttributeType):
+        (WebCore::SVGAnimateTransformElement::determineAnimatedAttributeType):
+        (WebCore::SVGAnimateTransformElement::resetToBaseValue):
+        (WebCore::SVGAnimateTransformElement::calculateAnimatedValue):
+        (WebCore::SVGAnimateTransformElement::calculateFromAndByValues):
+        (WebCore::SVGAnimateTransformElement::applyResultsToTarget):
+        (WebCore::SVGAnimateTransformElement::calculateDistance):
+        * svg/SVGAnimateTransformElement.h:
+        * svg/SVGAnimationElement.cpp:
+        (WebCore::parseKeyTimes):
+        (WebCore::parseKeySplines):
+        (WebCore::SVGAnimationElement::isTargetAttributeCSSProperty):
+        (WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue):
+        (WebCore::SVGAnimationElement::calculateKeyTimesForCalcModePaced):
+        (WebCore::solveEpsilon):
+        (WebCore::SVGAnimationElement::calculatePercentFromKeyPoints):
+        (WebCore::SVGAnimationElement::currentValuesFromKeyPoints):
+        (WebCore::SVGAnimationElement::currentValuesForValuesAnimation):
+        (WebCore::SVGAnimationElement::startedActiveInterval):
+        * svg/SVGAnimationElement.h:
+        * svg/SVGFilterElement.cpp:
+        (WebCore::SVGFilterElement::fillAttributeToPropertyTypeMap):
+        * svg/SVGGElement.cpp:
+        (WebCore::SVGGElement::attributeToPropertyTypeMap):
+        (WebCore::SVGGElement::fillAttributeToPropertyTypeMap): Added to fill the animated attribute map for this element.
+        * svg/SVGGElement.h:
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::fillAttributeToPropertyTypeMap): Changed attribute type to AnimatedString for xlink:href.
+        * svg/animation/SMILTimeContainer.cpp:
+        (WebCore::SMILTimeContainer::baseValueFor):
+        (WebCore::SMILTimeContainer::updateAnimations):
+        * svg/animation/SMILTimeContainer.h:
+        * svg/animation/SVGSMILElement.cpp:
+        (WebCore::SVGSMILElement::SVGSMILElement):
+        (WebCore::constructQualifiedName): Create a QualifiedName from a attribute name.
+        (WebCore::SVGSMILElement::insertedIntoDocument): Update local varaible of attribute name.
+        (WebCore::SVGSMILElement::removedFromDocument): Ditto.
+        (WebCore::SVGSMILElement::attributeChanged): Ditto.
+        * svg/animation/SVGSMILElement.h:
+        (WebCore::SVGSMILElement::attributeName):
+
 2011-02-20  David Kilzer  <ddkilzer@apple.com>
 
         BUILD FIX: Add missing UNUSED_PARAM() when !ENABLE(FULLSCREEN_API)
index a17364d..33ca46b 100644 (file)
@@ -45,7 +45,7 @@ namespace WebCore {
 
 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, Document* document)
     : SVGAnimationElement(tagName, document)
-    , m_propertyType(StringProperty)
+    , m_animatedAttributeType(AnimatedString)
     , m_fromNumber(0)
     , m_toNumber(0)
     , m_animatedNumber(numeric_limits<double>::infinity())
@@ -98,7 +98,7 @@ static inline void adjustForCurrentColor(SVGElement* targetElement, Color& color
         color = Color();
 }
 
-static inline void adjustForInheritance(SVGElement* targetElement, const String& attributeName, String& value)
+static inline void adjustForInheritance(SVGElement* targetElement, const QualifiedName& attributeName, String& value)
 {
     // FIXME: At the moment the computed style gets returned as a String and needs to get parsed again.
     // In the future we might want to work with the value type directly to avoid the String parsing.
@@ -110,24 +110,58 @@ static inline void adjustForInheritance(SVGElement* targetElement, const String&
 
     SVGElement* svgParent = static_cast<SVGElement*>(parent);
     if (svgParent->isStyled())
-        value = computedStyle(svgParent)->getPropertyValue(cssPropertyID(attributeName));
+        value = computedStyle(svgParent)->getPropertyValue(cssPropertyID(attributeName.localName()));
 }
 
-SVGAnimateElement::PropertyType SVGAnimateElement::determinePropertyType(const String& attribute) const
+bool SVGAnimateElement::hasValidAttributeType() const
 {
-    // FIXME: We should not allow animation of attribute types other than AnimatedColor for <animateColor>.
-    if (hasTagName(SVGNames::animateColorTag))
-        return ColorProperty;
-
-    // FIXME: Now that we have a full property table we need a more granular type specific animation.
-    AnimatedAttributeType type = targetElement()->animatedPropertyTypeForAttribute(QualifiedName(nullAtom, attribute, nullAtom));
-    if (type == AnimatedColor)
-        return ColorProperty;
-    if (type == AnimatedPath)
-        return PathProperty;
-    if (type == AnimatedPoints)
-        return PointsProperty;
-    return NumberProperty;
+    SVGElement* targetElement = this->targetElement();
+    if (!targetElement)
+        return false;
+    
+    return determineAnimatedAttributeType(targetElement) != AnimatedUnknown;
+}
+
+AnimatedAttributeType SVGAnimateElement::determineAnimatedAttributeType(SVGElement* targetElement) const
+{
+    ASSERT(targetElement);
+
+    AnimatedAttributeType type = targetElement->animatedPropertyTypeForAttribute(attributeName());
+    if (type == AnimatedUnknown || (hasTagName(SVGNames::animateColorTag) && type != AnimatedColor))
+        return AnimatedUnknown;
+
+    // FIXME: We need type specific animations in the future. Many animations marked as AnimatedString today will
+    // support continuous animations.
+    switch (type) {
+    case AnimatedBoolean:
+    case AnimatedEnumeration:
+    case AnimatedLengthList:
+    case AnimatedNumberList:
+    case AnimatedNumberOptionalNumber:
+    case AnimatedPreserveAspectRatio:
+    case AnimatedRect:
+    case AnimatedString:
+        return AnimatedString;
+    case AnimatedAngle:
+    case AnimatedInteger:
+    case AnimatedLength:
+    case AnimatedNumber:
+        return AnimatedNumber;
+    case AnimatedPath:
+        return AnimatedPath;
+    case AnimatedPoints:
+        return AnimatedPoints;
+    case AnimatedColor:
+        return AnimatedColor;
+    case AnimatedUnknown:
+    case AnimatedTransformList:
+        // Animations of transform lists are not allowed for <animate> or <set>
+        // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties
+        return AnimatedUnknown;
+    }
+
+    ASSERT_NOT_REACHED();
+    return AnimatedUnknown;
 }
 
 void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
@@ -152,9 +186,9 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
         return;
     SVGAnimateElement* results = static_cast<SVGAnimateElement*>(resultElement);
     // Can't accumulate over a string property.
-    if (results->m_propertyType == StringProperty && m_propertyType != StringProperty)
+    if (results->m_animatedAttributeType == AnimatedString && m_animatedAttributeType != AnimatedString)
         return;
-    if (m_propertyType == NumberProperty) {
+    if (m_animatedAttributeType == AnimatedNumber) {
         // To animation uses contributions from the lower priority animations as the base value.
         if (animationMode == ToAnimation)
             m_fromNumber = results->m_animatedNumber;
@@ -188,7 +222,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
             results->m_animatedNumber = number;
         return;
     } 
-    if (m_propertyType == ColorProperty) {
+    if (m_animatedAttributeType == AnimatedColor) {
         if (animationMode == ToAnimation)
             m_fromColor = results->m_animatedColor;
 
@@ -221,7 +255,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
             results->m_animatedColor = color;
         return;
     }
-    if (m_propertyType == PathProperty) {
+    if (m_animatedAttributeType == AnimatedPath) {
         if (animationMode == ToAnimation) {
             ASSERT(results->m_animatedPathPointer);
             m_fromPath = results->m_animatedPathPointer->copy();
@@ -230,7 +264,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
             ASSERT(m_fromPath);
             ASSERT(percentage >= 0);
             results->m_animatedPathPointer = m_fromPath.get();
-        } else if (percentage == 1.f) {
+        } else if (percentage == 1) {
             ASSERT(m_toPath);
             results->m_animatedPathPointer = m_toPath.get();
         } else {
@@ -248,16 +282,16 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
                 ASSERT(m_fromPath);
                 ASSERT(m_toPath);
                 ASSERT(!results->m_animatedPath);
-                results->m_animatedPathPointer = ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1.0f
+                results->m_animatedPathPointer = ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1) 
                     ? m_toPath.get() : m_fromPath.get();
             }
         }
         return;
     }
-    if (m_propertyType == PointsProperty) {
+    if (m_animatedAttributeType == AnimatedPoints) {
         if (!percentage)
             results->m_animatedPoints = m_fromPoints;
-        else if (percentage == 1.f)
+        else if (percentage == 1)
             results->m_animatedPoints = m_toPoints;
         else {
             if (!m_fromPoints.isEmpty() && !m_toPoints.isEmpty())
@@ -266,7 +300,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
                 results->m_animatedPoints.clear();
             // Fall back to discrete animation if the points are not compatible
             if (results->m_animatedPoints.isEmpty())
-                results->m_animatedPoints = ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1.0f
+                results->m_animatedPoints = ((animationMode == FromToAnimation && percentage > 0.5f) || animationMode == ToAnimation || percentage == 1) 
                     ? m_toPoints : m_fromPoints;
         }
         return;
@@ -283,17 +317,17 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeat
     else
         results->m_animatedString = m_fromString;
     // Higher priority replace animation overrides any additive results so far.
-    results->m_propertyType = StringProperty;
+    results->m_animatedAttributeType = AnimatedString;
 }
 
-static bool inheritsFromProperty(SVGElement* targetElement, const String& attributeName, const String& value)
+static bool inheritsFromProperty(SVGElement* targetElement, const QualifiedName& attributeName, const String& value)
 {
     ASSERT(targetElement);
     DEFINE_STATIC_LOCAL(const AtomicString, inherit, ("inherit"));
 
     if (value.isEmpty() || value != inherit || !targetElement->isStyled())
         return false;
-    return SVGStyledElement::isAnimatableCSSProperty(QualifiedName(nullAtom, attributeName, nullAtom));
+    return SVGStyledElement::isAnimatableCSSProperty(attributeName);
 }
 
 static bool attributeValueIsCurrentColor(const String& value)
@@ -311,8 +345,8 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
     m_toPropertyValueType = inheritsFromProperty(targetElement, attributeName(), toString) ? InheritValue : RegularPropertyValue;
 
     // FIXME: Needs more solid way determine target attribute type.
-    m_propertyType = determinePropertyType(attributeName());
-    if (m_propertyType == ColorProperty) {
+    m_animatedAttributeType = determineAnimatedAttributeType(targetElement);
+    if (m_animatedAttributeType == AnimatedColor) {
         bool fromIsCurrentColor = attributeValueIsCurrentColor(fromString);
         bool toIsCurrentColor = attributeValueIsCurrentColor(toString);
         if (fromIsCurrentColor)
@@ -327,14 +361,14 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
         bool toIsValid = m_toColor.isValid() || toIsCurrentColor || m_toPropertyValueType == InheritValue;
         if ((fromIsValid && toIsValid) || (toIsValid && animationMode() == ToAnimation))
             return true;
-    } else if (m_propertyType == NumberProperty) {
+    } else if (m_animatedAttributeType == AnimatedNumber) {
         m_numberUnit = String();
         if (parseNumberValueAndUnit(toString, m_toNumber, m_numberUnit)) {
             // For to-animations the from number is calculated later
             if (animationMode() == ToAnimation || parseNumberValueAndUnit(fromString, m_fromNumber, m_numberUnit))
                 return true;
         }
-    } else if (m_propertyType == PathProperty) {
+    } else if (m_animatedAttributeType == AnimatedPath) {
         SVGPathParserFactory* factory = SVGPathParserFactory::self();
         if (factory->buildSVGPathByteStreamFromString(toString, m_toPath, UnalteredParsing)) {
             // For to-animations the from number is calculated later
@@ -343,7 +377,7 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
         }
         m_fromPath.clear();
         m_toPath.clear();
-    } else if (m_propertyType == PointsProperty) {
+    } else if (m_animatedAttributeType == AnimatedPoints) {
         m_fromPoints.clear();
         if (pointsListFromSVGData(m_fromPoints, fromString)) {
             m_toPoints.clear();
@@ -353,7 +387,7 @@ bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
     }
     m_fromString = fromString;
     m_toString = toString;
-    m_propertyType = StringProperty;
+    m_animatedAttributeType = AnimatedString;
     return true;
 }
 
@@ -366,8 +400,8 @@ bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const
     m_toPropertyValueType = inheritsFromProperty(targetElement, attributeName(), byString) ? InheritValue : RegularPropertyValue;
 
     ASSERT(!hasTagName(SVGNames::setTag));
-    m_propertyType = determinePropertyType(attributeName());
-    if (m_propertyType == ColorProperty) {
+    m_animatedAttributeType = determineAnimatedAttributeType(targetElement);
+    if (m_animatedAttributeType == AnimatedColor) {
         bool fromIsCurrentColor = attributeValueIsCurrentColor(fromString);
         bool byIsCurrentColor = attributeValueIsCurrentColor(byString);
         if (fromIsCurrentColor)
@@ -396,16 +430,18 @@ bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const
 
 void SVGAnimateElement::resetToBaseValue(const String& baseString)
 {
+    SVGElement* targetElement = this->targetElement();
+    ASSERT(targetElement);
     m_animatedString = baseString;
-    PropertyType lastType = m_propertyType;
-    m_propertyType = determinePropertyType(attributeName());
-    if (m_propertyType == ColorProperty) {
+    AnimatedAttributeType lastType = m_animatedAttributeType;
+    m_animatedAttributeType = determineAnimatedAttributeType(targetElement);
+    if (m_animatedAttributeType == AnimatedColor) {
         m_animatedColor = baseString.isEmpty() ? Color() : SVGColor::colorFromRGBColorString(baseString);
         if (isContributing(elapsed())) {
-            m_propertyType = lastType;
+            m_animatedAttributeType = lastType;
             return;
         }
-    } else if (m_propertyType == NumberProperty) {
+    } else if (m_animatedAttributeType == AnimatedNumber) {
         if (baseString.isEmpty()) {
             m_animatedNumber = 0;
             m_numberUnit = String();
@@ -413,27 +449,27 @@ void SVGAnimateElement::resetToBaseValue(const String& baseString)
         }
         if (parseNumberValueAndUnit(baseString, m_animatedNumber, m_numberUnit))
             return;
-    } else if (m_propertyType == PathProperty) {
+    } else if (m_animatedAttributeType == AnimatedPath) {
         m_animatedPath.clear();
         SVGPathParserFactory* factory = SVGPathParserFactory::self();
         factory->buildSVGPathByteStreamFromString(baseString, m_animatedPath, UnalteredParsing);
         m_animatedPathPointer = m_animatedPath.get();
         return;
-    } else if (m_propertyType == PointsProperty) {
+    } else if (m_animatedAttributeType == AnimatedPoints) {
         m_animatedPoints.clear();
         return;
     }
-    m_propertyType = StringProperty;
+    m_animatedAttributeType = AnimatedString;
 }
     
 void SVGAnimateElement::applyResultsToTarget()
 {
     String valueToApply;
-    if (m_propertyType == ColorProperty)
+    if (m_animatedAttributeType == AnimatedColor)
         valueToApply = m_animatedColor.serialized();
-    else if (m_propertyType == NumberProperty)
+    else if (m_animatedAttributeType == AnimatedNumber)
         valueToApply = String::number(m_animatedNumber) + m_numberUnit;
-    else if (m_propertyType == PathProperty) {
+    else if (m_animatedAttributeType == AnimatedPath) {
         if (!m_animatedPathPointer || m_animatedPathPointer->isEmpty())
             valueToApply = m_animatedString;
         else {
@@ -444,7 +480,7 @@ void SVGAnimateElement::applyResultsToTarget()
             SVGPathParserFactory* factory = SVGPathParserFactory::self();
             factory->buildStringFromByteStream(m_animatedPathPointer, valueToApply, UnalteredParsing);
         }
-    } else if (m_propertyType == PointsProperty)
+    } else if (m_animatedAttributeType == AnimatedPoints)
         valueToApply = m_animatedPoints.isEmpty() ? m_animatedString : m_animatedPoints.valueAsString();
     else
         valueToApply = m_animatedString;
@@ -454,31 +490,31 @@ void SVGAnimateElement::applyResultsToTarget()
     
 float SVGAnimateElement::calculateDistance(const String& fromString, const String& toString)
 {
-    m_propertyType = determinePropertyType(attributeName());
-    if (m_propertyType == NumberProperty) {
+    SVGElement* targetElement = this->targetElement();
+    if (!targetElement)
+        return -1;
+    m_animatedAttributeType = determineAnimatedAttributeType(targetElement);
+    if (m_animatedAttributeType == AnimatedNumber) {
         double from;
         double to;
         String unit;
         if (!parseNumberValueAndUnit(fromString, from, unit))
-            return -1.f;
+            return -1;
         if (!parseNumberValueAndUnit(toString, to, unit))
-            return -1.f;
+            return -1;
         return narrowPrecisionToFloat(fabs(to - from));
     }
-    if (m_propertyType == ColorProperty) {
+    if (m_animatedAttributeType == AnimatedColor) {
         Color from = SVGColor::colorFromRGBColorString(fromString);
         if (!from.isValid())
-            return -1.f;
+            return -1;
         Color to = SVGColor::colorFromRGBColorString(toString);
         if (!to.isValid())
-            return -1.f;
+            return -1;
         return ColorDistance(from, to).distance();
     }
-    return -1.f;
+    return -1;
 }
    
 }
-
-// vim:ts=4:noet
 #endif // ENABLE(SVG)
-
index 70c0dd0..75be4b2 100644 (file)
@@ -58,9 +58,10 @@ private:
         CurrentColorValue,
         InheritValue
     };
-    enum PropertyType { NumberProperty, ColorProperty, StringProperty, PathProperty, PointsProperty };
-    PropertyType determinePropertyType(const String& attribute) const;
-    PropertyType m_propertyType;
+    
+    virtual bool hasValidAttributeType() const;
+    AnimatedAttributeType determineAnimatedAttributeType(SVGElement*) const;
+    AnimatedAttributeType m_animatedAttributeType;
 
     AnimatedPropertyValueType m_fromPropertyValueType;
     AnimatedPropertyValueType m_toPropertyValueType;
index ec51548..e0202e4 100644 (file)
@@ -53,14 +53,17 @@ PassRefPtr<SVGAnimateMotionElement> SVGAnimateMotionElement::create(const Qualif
     return adoptRef(new SVGAnimateMotionElement(tagName, document));
 }
 
-bool SVGAnimateMotionElement::hasValidTarget() const
+bool SVGAnimateMotionElement::hasValidAttributeType() const
 {
-    if (!SVGAnimationElement::hasValidTarget())
-        return false;
     SVGElement* targetElement = this->targetElement();
+    if (!targetElement)
+        return false;
+
+    // We don't have a special attribute name to verify the animation type. Check the element name instead.
     if (!targetElement->isStyledTransformable() && !targetElement->hasTagName(SVGNames::textTag))
         return false;
     // Spec: SVG 1.1 section 19.2.15
+    // FIXME: svgTag is missing. Needs to be checked, if transforming <svg> could cause problems.
     if (targetElement->hasTagName(gTag)
         || targetElement->hasTagName(defsTag)
         || targetElement->hasTagName(useTag)
@@ -134,11 +137,11 @@ static bool parsePoint(const String& s, FloatPoint& point)
     if (!skipOptionalSpaces(cur, end))
         return false;
     
-    float x = 0.0f;
+    float x = 0;
     if (!parseNumber(cur, end, x))
         return false;
     
-    float y = 0.0f;
+    float y = 0;
     if (!parseNumber(cur, end, y))
         return false;
     
@@ -150,10 +153,9 @@ static bool parsePoint(const String& s, FloatPoint& point)
     
 void SVGAnimateMotionElement::resetToBaseValue(const String&)
 {
-    if (!hasValidTarget())
+    if (!hasValidAttributeType())
         return;
-    SVGElement* target = targetElement();
-    AffineTransform* transform = target->supplementalTransform();
+    AffineTransform* transform = targetElement()->supplementalTransform();
     if (!transform)
         return;
     transform->makeIdentity();
@@ -177,15 +179,15 @@ bool SVGAnimateMotionElement::calculateFromAndByValues(const String& fromString,
 
 void SVGAnimateMotionElement::calculateAnimatedValue(float percentage, unsigned, SVGSMILElement*)
 {
-    SVGElement* target = targetElement();
-    if (!target)
+    SVGElement* targetElement = this->targetElement();
+    if (!targetElement)
         return;
-    AffineTransform* transform = target->supplementalTransform();
+    AffineTransform* transform = targetElement->supplementalTransform();
     if (!transform)
         return;
 
-    if (target->renderer())
-        target->renderer()->setNeedsTransformUpdate();
+    if (RenderObject* targetRenderer = targetElement->renderer())
+        targetRenderer->setNeedsTransformUpdate();
 
     if (!isAdditive())
         transform->makeIdentity();
@@ -204,7 +206,7 @@ void SVGAnimateMotionElement::calculateAnimatedValue(float percentage, unsigned,
             if (rotateMode == RotateAuto || rotateMode == RotateAutoReverse) {
                 float angle = path.normalAngleAtLength(positionOnPath, ok);
                 if (rotateMode == RotateAutoReverse)
-                    angle += 180.f;
+                    angle += 180;
                 transform->rotate(angle);
             }
         }
@@ -250,13 +252,12 @@ float SVGAnimateMotionElement::calculateDistance(const String& fromString, const
     FloatPoint from;
     FloatPoint to;
     if (!parsePoint(fromString, from))
-        return -1.f;
+        return -1;
     if (!parsePoint(toString, to))
-        return -1.f;
+        return -1;
     FloatSize diff = to - from;
     return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
 }
 
 }
-
 #endif // ENABLE(SVG)
index 7e168c3..96861b6 100644 (file)
@@ -34,7 +34,7 @@ public:
 private:
     SVGAnimateMotionElement(const QualifiedName&, Document*);
 
-    virtual bool hasValidTarget() const;
+    virtual bool hasValidAttributeType() const;
 
     virtual void parseMappedAttribute(Attribute*);
 
@@ -73,5 +73,3 @@ private:
 
 #endif // ENABLE(SVG_ANIMATION)
 #endif // SVGAnimateMotionElement_h
-
-// vim:ts=4:noet
index bdcab38..6e1fb99 100644 (file)
@@ -59,14 +59,25 @@ PassRefPtr<SVGAnimateTransformElement> SVGAnimateTransformElement::create(const
     return adoptRef(new SVGAnimateTransformElement(tagName, document));
 }
 
-bool SVGAnimateTransformElement::hasValidTarget() const
+bool SVGAnimateTransformElement::hasValidAttributeType() const
 {
     SVGElement* targetElement = this->targetElement();
-    return SVGAnimationElement::hasValidTarget()
-        && (targetElement->isStyledTransformable()
-        || targetElement->hasTagName(SVGNames::textTag)
-        || targetElement->hasTagName(SVGNames::linearGradientTag)
-        || targetElement->hasTagName(SVGNames::radialGradientTag));
+    if (!targetElement)
+        return false;
+    
+    return determineAnimatedAttributeType(targetElement) == AnimatedTransformList;
+}
+
+AnimatedAttributeType SVGAnimateTransformElement::determineAnimatedAttributeType(SVGElement* targetElement) const
+{
+    ASSERT(targetElement);
+    
+    // Just transform lists can be animated with <animateTransform>
+    // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties
+    if (targetElement->animatedPropertyTypeForAttribute(attributeName()) != AnimatedTransformList)
+        return AnimatedUnknown;
+
+    return AnimatedTransformList;
 }
 
 void SVGAnimateTransformElement::parseMappedAttribute(Attribute* attr)
@@ -102,26 +113,27 @@ static SVGTransformList* transformListFor(SVGElement* element)
     
 void SVGAnimateTransformElement::resetToBaseValue(const String& baseValue)
 {
-    if (!hasValidTarget())
+    SVGElement* targetElement = this->targetElement();
+    if (!targetElement || determineAnimatedAttributeType(targetElement) == AnimatedUnknown)
         return;
 
-    if (targetElement()->hasTagName(SVGNames::linearGradientTag) || targetElement()->hasTagName(SVGNames::radialGradientTag)) {
-        targetElement()->setAttribute(SVGNames::gradientTransformAttr, baseValue.isEmpty() ? "matrix(1 0 0 1 0 0)" : baseValue);
+    if (targetElement->hasTagName(SVGNames::linearGradientTag) || targetElement->hasTagName(SVGNames::radialGradientTag)) {
+        targetElement->setAttribute(SVGNames::gradientTransformAttr, baseValue.isEmpty() ? "matrix(1 0 0 1 0 0)" : baseValue);
         return;
     }
 
     if (baseValue.isEmpty()) {
-        if (SVGTransformList* list = transformListFor(targetElement()))
+        if (SVGTransformList* list = transformListFor(targetElement))
             list->clear();
     } else
-        targetElement()->setAttribute(SVGNames::transformAttr, baseValue);
+        targetElement->setAttribute(SVGNames::transformAttr, baseValue);
 }
 
-void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement* resultElement)
+void SVGAnimateTransformElement::calculateAnimatedValue(float percentage, unsigned repeat, SVGSMILElement*)
 {
-    if (!hasValidTarget())
+    SVGElement* targetElement = this->targetElement();
+    if (!targetElement || determineAnimatedAttributeType(targetElement) == AnimatedUnknown)
         return;
-    SVGElement* targetElement = resultElement->targetElement();
     SVGTransformList* transformList = transformListFor(targetElement);
     ASSERT(transformList);
 
@@ -146,7 +158,6 @@ bool SVGAnimateTransformElement::calculateFromAndToValues(const String& fromStri
 
 bool SVGAnimateTransformElement::calculateFromAndByValues(const String& fromString, const String& byString)
 {
-
     m_fromTransform = parseTransformValue(fromString);
     if (!m_fromTransform.isValid())
         return false;
@@ -168,13 +179,11 @@ SVGTransform SVGAnimateTransformElement::parseTransformValue(const String& value
     
 void SVGAnimateTransformElement::applyResultsToTarget()
 {
-    if (!hasValidTarget())
-        return;
-    // We accumulate to the target element transform list so there is not much to do here.
     SVGElement* targetElement = this->targetElement();
-    if (!targetElement)
+    if (!targetElement || determineAnimatedAttributeType(targetElement) == AnimatedUnknown)
         return;
 
+    // We accumulate to the target element transform list so there is not much to do here.
     if (RenderObject* renderer = targetElement->renderer()) {
         renderer->setNeedsTransformUpdate();
         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
@@ -210,10 +219,10 @@ float SVGAnimateTransformElement::calculateDistance(const String& fromString, co
     // is paced separately. To implement this we need to treat each component as individual animation everywhere.
     SVGTransform from = parseTransformValue(fromString);
     if (!from.isValid())
-        return -1.f;
+        return -1;
     SVGTransform to = parseTransformValue(toString);
     if (!to.isValid() || from.type() != to.type())
-        return -1.f;
+        return -1;
     if (to.type() == SVGTransform::SVG_TRANSFORM_TRANSLATE) {
         FloatSize diff = to.translate() - from.translate();
         return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
@@ -224,11 +233,8 @@ float SVGAnimateTransformElement::calculateDistance(const String& fromString, co
         FloatSize diff = to.scale() - from.scale();
         return sqrtf(diff.width() * diff.width() + diff.height() * diff.height());
     }
-    return -1.f;
+    return -1;
 }
 
 }
-
-// vim:ts=4:noet
 #endif // ENABLE(SVG)
-
index 0f806d7..6ebc97e 100644 (file)
@@ -39,7 +39,8 @@ public:
 private:
     SVGAnimateTransformElement(const QualifiedName&, Document*);
     
-    virtual bool hasValidTarget() const;
+    virtual bool hasValidAttributeType() const;
+    AnimatedAttributeType determineAnimatedAttributeType(SVGElement*) const;
 
     virtual void parseMappedAttribute(Attribute*);
 
@@ -64,5 +65,3 @@ private:
 
 #endif // ENABLE(SVG)
 #endif // SVGAnimateTransformElement_h
-
-// vim:ts=4:noet
index 0e7f820..21784c2 100644 (file)
@@ -69,7 +69,7 @@ static void parseKeyTimes(const String& parse, Vector<float>& result, bool verif
         String timeString = parseList[n];
         bool ok;
         float time = timeString.toFloat(&ok);
-        if (!ok || time < 0 || time > 1.f)
+        if (!ok || time < 0 || time > 1)
             goto fail;
         if (verifyOrder) {
             if (!n) {
@@ -98,25 +98,25 @@ static void parseKeySplines(const String& parse, Vector<UnitBezier>& result)
     bool delimParsed = false;
     while (cur < end) {
         delimParsed = false;
-        float posA = 0.0f;
+        float posA = 0;
         if (!parseNumber(cur, end, posA)) {
             result.clear();
             return;
         }
 
-        float posB = 0.0f;
+        float posB = 0;
         if (!parseNumber(cur, end, posB)) {
             result.clear();
             return;
         }
 
-        float posC = 0.0f;
+        float posC = 0;
         if (!parseNumber(cur, end, posC)) {
             result.clear();
             return;
         }
 
-        float posD = 0.0f;
+        float posD = 0;
         if (!parseNumber(cur, end, posD, false)) {
             result.clear();
             return;
@@ -290,27 +290,22 @@ bool SVGAnimationElement::isAccumulated() const
     return value == sum && animationMode() != ToAnimation;
 }
 
-bool SVGAnimationElement::hasValidTarget() const
-{
-    return targetElement();
-}
-
-bool SVGAnimationElement::isTargetAttributeCSSProperty(SVGElement* targetElement, const String& attributeName)
+bool SVGAnimationElement::isTargetAttributeCSSProperty(SVGElement* targetElement, const QualifiedName& attributeName)
 {
     ASSERT(targetElement);
     if (!targetElement->isStyled())
         return false;
 
-    return SVGStyledElement::isAnimatableCSSProperty(QualifiedName(nullAtom, attributeName, nullAtom));
+    return SVGStyledElement::isAnimatableCSSProperty(attributeName);
 }
 
 void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value)
 {
-    if (!hasValidTarget())
+    if (!hasValidAttributeType())
         return;
     SVGElement* targetElement = this->targetElement();
-    String attributeName = this->attributeName();
-    if (!targetElement || attributeName.isEmpty() || value.isNull())
+    QualifiedName attributeName = this->attributeName();
+    if (!targetElement || attributeName == anyQName() || value.isNull())
         return;
 
     // We don't want the instance tree to get rebuild. Instances are updated in the loop below.
@@ -326,7 +321,7 @@ void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value)
     if (attributeIsCSSProperty) {
         // FIXME: This should set the override style, not the inline style.
         // Sadly override styles are not yet implemented.
-        targetElement->style()->setProperty(attributeName, value, "", ec);
+        targetElement->style()->setProperty(attributeName.localName(), value, "", ec);
     } else {
         // FIXME: This should set the 'presentation' value, not the actual 
         // attribute value. Whatever that means in practice.
@@ -344,7 +339,7 @@ void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value)
         if (!shadowTreeElement)
             continue;
         if (attributeIsCSSProperty)
-            shadowTreeElement->style()->setProperty(attributeName, value, "", ec);
+            shadowTreeElement->style()->setProperty(attributeName.localName(), value, "", ec);
         else
             shadowTreeElement->setAttribute(attributeName, value, ec);
         (*it)->correspondingUseElement()->setNeedsStyleRecalc();
@@ -375,13 +370,13 @@ void SVGAnimationElement::calculateKeyTimesForCalcModePaced()
     // Normalize.
     for (unsigned n = 1; n < keyTimesForPaced.size() - 1; ++n)
         keyTimesForPaced[n] = keyTimesForPaced[n - 1] + keyTimesForPaced[n] / totalDistance;
-    keyTimesForPaced[keyTimesForPaced.size() - 1] = 1.f;
+    keyTimesForPaced[keyTimesForPaced.size() - 1] = 1;
 
     // Use key times calculated based on pacing instead of the user provided ones.
     m_keyTimes.swap(keyTimesForPaced);
 }
 
-static inline double solveEpsilon(double duration) { return 1. / (200. * duration); }
+static inline double solveEpsilon(double duration) { return 1 / (200 * duration); }
 
 unsigned SVGAnimationElement::calculateKeyTimesIndex(float percent) const
 {
@@ -419,9 +414,9 @@ float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const
     float toKeyPoint = m_keyPoints[index + 1];
     
     if (calcMode() == CalcModeDiscrete)
-        return percent == 1.0f ? toKeyPoint : fromKeyPoint;
+        return percent == 1 ? toKeyPoint : fromKeyPoint;
     
-    float keyPointPercent = percent == 1.0f ? 1.0f : (percent - fromPercent) / (toPercent - fromPercent);
+    float keyPointPercent = percent == 1 ? 1 : (percent - fromPercent) / (toPercent - fromPercent);
     
     if (calcMode() == CalcModeSpline) {
         ASSERT(m_keySplines.size() == m_keyPoints.size() - 1);
@@ -436,7 +431,7 @@ void SVGAnimationElement::currentValuesFromKeyPoints(float percent, float& effec
     ASSERT(m_keyPoints.size() == m_keyTimes.size());
     ASSERT(calcMode() != CalcModePaced);
     effectivePercent = calculatePercentFromKeyPoints(percent);
-    unsigned index = effectivePercent == 1.0f ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1));
+    unsigned index = effectivePercent == 1 ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1));
     from = m_values[index];
     to = m_values[index + 1];
 }
@@ -458,10 +453,10 @@ void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float&
     unsigned index = calculateKeyTimesIndex(percent);
     if (calcMode == CalcModeDiscrete) {
         if (!keyTimesCount) 
-            index = percent == 1.0f ? valuesCount - 1 : static_cast<unsigned>(percent * valuesCount);
+            index = percent == 1 ? valuesCount - 1 : static_cast<unsigned>(percent * valuesCount);
         from = m_values[index];
         to = m_values[index];
-        effectivePercent = 0.0f;
+        effectivePercent = 0;
         return;
     }
     
@@ -481,7 +476,7 @@ void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float&
     from = m_values[index];
     to = m_values[index + 1];
     ASSERT(toPercent > fromPercent);
-    effectivePercent = percent == 1.0f ? 1.0f : (percent - fromPercent) / (toPercent - fromPercent);
+    effectivePercent = percent == 1 ? 1 : (percent - fromPercent) / (toPercent - fromPercent);
     
     if (calcMode == CalcModeSpline) {
         ASSERT(m_keySplines.size() == m_values.size() - 1);
@@ -493,7 +488,7 @@ void SVGAnimationElement::startedActiveInterval()
 {
     m_animationValid = false;
 
-    if (!hasValidTarget())
+    if (!hasValidAttributeType())
         return;
 
     // These validations are appropriate for all animation modes.
@@ -569,7 +564,5 @@ void SVGAnimationElement::endedActiveInterval()
 }
 
 }
-
-// vim:ts=4:noet
 #endif // ENABLE(SVG_ANIMATION)
 
index d968f35..8aa2cdb 100644 (file)
@@ -56,7 +56,7 @@ public:
     virtual void endElement();
     virtual void endElementAt(float offset);
 
-    static bool isTargetAttributeCSSProperty(SVGElement*, const String&);
+    static bool isTargetAttributeCSSProperty(SVGElement*, const QualifiedName&);
 
 protected:
     SVGAnimationElement(const QualifiedName&, Document*);
@@ -75,8 +75,6 @@ protected:
     
     enum AnimationMode { NoAnimation, ToAnimation, ByAnimation, ValuesAnimation, FromToAnimation, FromByAnimation, PathAnimation };
     AnimationMode animationMode() const;
-
-    virtual bool hasValidTarget() const;
     
     String targetAttributeBaseValue() const;
     void setTargetAttributeAnimatedValue(const String&);
index 539d4df..a3b5e7c 100644 (file)
@@ -214,7 +214,7 @@ void SVGFilterElement::fillAttributeToPropertyTypeMap()
     attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength);
     attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength);
     attributeToPropertyTypeMap.set(SVGNames::filterResAttr, AnimatedNumberOptionalNumber);
-    attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedEnumeration);
+    attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedString);
 }
 
 void SVGFilterElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
index 233aa74..6105194 100644 (file)
@@ -93,6 +93,17 @@ void SVGGElement::synchronizeProperty(const QualifiedName& attrName)
         SVGTests::synchronizeProperties(this, attrName);
 }
 
+AttributeToPropertyTypeMap& SVGGElement::attributeToPropertyTypeMap()
+{
+    DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
+    return s_attributeToPropertyTypeMap;
+}
+
+void SVGGElement::fillAttributeToPropertyTypeMap()
+{
+    SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap());
+}
+
 RenderObject* SVGGElement::createRenderer(RenderArena* arena, RenderStyle* style)
 {
     // SVG 1.1 testsuite explicitely uses constructs like <g display="none"><linearGradient>
index 3c00b34..c306f4a 100644 (file)
@@ -50,6 +50,8 @@ private:
     virtual void parseMappedAttribute(Attribute*);
     virtual void svgAttributeChanged(const QualifiedName&);
     virtual void synchronizeProperty(const QualifiedName&);
+    virtual void fillAttributeToPropertyTypeMap();
+    virtual AttributeToPropertyTypeMap& attributeToPropertyTypeMap();
 
     virtual bool rendererIsNeeded(RenderStyle*);
 
index cc53bda..a8a1cf9 100644 (file)
@@ -242,7 +242,7 @@ void SVGUseElement::fillAttributeToPropertyTypeMap()
     attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedLength);
     attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength);
     attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength);
-    attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedLength);
+    attributeToPropertyTypeMap.set(XLinkNames::hrefAttr, AnimatedString);
 }
 
 static void updateContainerSize(SVGUseElement* useElement, SVGElementInstance* targetInstance)
index cf7122e..0bacdb3 100644 (file)
@@ -197,12 +197,12 @@ String SMILTimeContainer::baseValueFor(ElementAttributePair key)
         return it->second;
     
     SVGElement* targetElement = key.first;
-    String attributeName = key.second;
+    QualifiedName attributeName = key.second;
     ASSERT(targetElement);
-    ASSERT(!attributeName.isEmpty());
+    ASSERT(attributeName != anyQName());
     String baseValue;
     if (SVGAnimationElement::isTargetAttributeCSSProperty(targetElement, attributeName))
-        baseValue = computedStyle(targetElement)->getPropertyValue(cssPropertyID(attributeName));
+        baseValue = computedStyle(targetElement)->getPropertyValue(cssPropertyID(attributeName.localName()));
     else
         baseValue = targetElement->getAttribute(attributeName);
     m_savedBaseValues.add(key, baseValue);
@@ -264,10 +264,11 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed)
         SVGElement* targetElement = animation->targetElement();
         if (!targetElement)
             continue;
-        String attributeName = animation->attributeName();
-        if (attributeName.isEmpty()) {
+        
+        QualifiedName attributeName = animation->attributeName();
+        if (attributeName == anyQName()) {
             if (animation->hasTagName(SVGNames::animateMotionTag))
-                attributeName = SVGNames::animateMotionTag.localName();
+                attributeName = SVGNames::animateMotionTag;
             else
                 continue;
         }
@@ -276,6 +277,8 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed)
         ElementAttributePair key(targetElement, attributeName); 
         SVGSMILElement* resultElement = resultsElements.get(key).get();
         if (!resultElement) {
+            if (!animation->hasValidAttributeType())
+                continue;
             resultElement = animation;
             resultElement->resetToBaseValue(baseValueFor(key));
             resultsElements.add(key, resultElement);
index bf734d3..2b46ff3 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(SVG)
 
+#include "QualifiedName.h"
 #include "PlatformString.h"
 #include "SMILTime.h"
 #include "Timer.h"
@@ -74,7 +75,7 @@ private:
     void updateDocumentOrderIndexes();
     void sortByPriority(Vector<SVGSMILElement*>& smilElements, SMILTime elapsed);
     
-    typedef pair<SVGElement*, String> ElementAttributePair;
+    typedef pair<SVGElement*, QualifiedName> ElementAttributePair;
     String baseValueFor(ElementAttributePair);
     
     double m_beginTime;
index 2364c6a..bcdcb78 100644 (file)
@@ -42,7 +42,6 @@
 #include "SVGSVGElement.h"
 #include "SVGURIReference.h"
 #include "XLinkNames.h"
-#include <math.h>
 #include <wtf/MathExtras.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
@@ -115,6 +114,7 @@ SVGSMILElement::Condition::Condition(Type type, BeginOrEnd beginOrEnd, const Str
     
 SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document* doc)
     : SVGElement(tagName, doc)
+    , m_attributeName(anyQName())
     , m_conditionsConnected(false)
     , m_hasEndEventConditions(false)
     , m_intervalBegin(SMILTime::unresolved())
@@ -140,6 +140,28 @@ SVGSMILElement::~SVGSMILElement()
     if (m_timeContainer)
         m_timeContainer->unschedule(this);
 }
+
+static inline QualifiedName constructQualifiedName(const SVGElement* svgElement, const String& attributeName)
+{
+    ASSERT(svgElement);
+    if (attributeName.isEmpty())
+        return anyQName();
+    if (!attributeName.contains(':'))
+        return QualifiedName(nullAtom, attributeName, nullAtom);
+    
+    String prefix;
+    String localName;
+    ExceptionCode ec = 0;
+    if (!Document::parseQualifiedName(attributeName, prefix, localName, ec))
+        return anyQName();
+    ASSERT(!ec);
+    
+    String namespaceURI = svgElement->lookupNamespaceURI(prefix);    
+    if (namespaceURI.isEmpty())
+        return anyQName();
+    
+    return QualifiedName(nullAtom, localName, namespaceURI);
+}
     
 void SVGSMILElement::insertedIntoDocument()
 {
@@ -149,6 +171,7 @@ void SVGSMILElement::insertedIntoDocument()
     for (ContainerNode* n = this; n; n = n->parentNode())
         ASSERT(!n->isShadowRoot());
 #endif
+    m_attributeName = constructQualifiedName(this, getAttribute(SVGNames::attributeNameAttr));
     SVGSVGElement* owner = ownerSVGElement();
     if (!owner)
         return;
@@ -160,6 +183,7 @@ void SVGSMILElement::insertedIntoDocument()
 
 void SVGSMILElement::removedFromDocument()
 {
+    m_attributeName = anyQName();
     if (m_timeContainer) {
         m_timeContainer->unschedule(this);
         m_timeContainer = 0;
@@ -380,7 +404,11 @@ void SVGSMILElement::attributeChanged(Attribute* attr, bool preserveDecls)
         m_cachedMin = invalidCachedTime;
     else if (attrName == SVGNames::maxAttr)
         m_cachedMax = invalidCachedTime;
-    
+    else if (attrName == SVGNames::attributeNameAttr) {
+        if (inDocument())
+            m_attributeName = constructQualifiedName(this, attr->value());
+    }
+
     if (inDocument()) {
         if (attrName == SVGNames::beginAttr)
             beginListChanged();
@@ -467,12 +495,7 @@ SVGElement* SVGSMILElement::targetElement() const
         return static_cast<SVGElement*>(target);
     return 0;
 }
-    
-String SVGSMILElement::attributeName() const
-{    
-    return getAttribute(SVGNames::attributeNameAttr).string().stripWhiteSpace();
-}
-    
+
 SMILTime SVGSMILElement::elapsed() const 
 {
     return m_timeContainer ? m_timeContainer->elapsed() : 0;
index 2135642..6d7fd01 100644 (file)
@@ -49,11 +49,13 @@ public:
     virtual void insertedIntoDocument();
     virtual void removedFromDocument();
     virtual void finishParsingChildren();
+    
+    virtual bool hasValidAttributeType() const = 0;
 
     SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
 
     SVGElement* targetElement() const;
-    String attributeName() const;
+    const QualifiedName& attributeName() const { return m_attributeName; }
 
     void beginByLinkActivation();
 
@@ -175,6 +177,8 @@ private:
         Frozen
     };
 
+    QualifiedName m_attributeName;
+
     ActiveState determineActiveState(SMILTime elapsed) const;
     float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
     SMILTime calculateNextProgressTime(SMILTime elapsed) const;