Changeset 109342 in webkit


Ignore:
Timestamp:
Mar 1, 2012 6:00:55 AM (12 years ago)
Author:
Nikolas Zimmermann
Message:

Introduce SMIL overrideStyle, to make SVG stop mutating CSS styles directly
https://bugs.webkit.org/show_bug.cgi?id=79790

Reviewed by Zoltan Herczeg.

Source/WebCore:

Next step towards enabling animVal support for XML attribute animations.
When SVG CSS properties are animated using SMIL, we currently mutate
the target elements style, and have to keep a baseValue around as String
to be able to recover from the DOM mutations at the end, if fill!="freeze".

The approach required by SMIL is to keep around an override style declaration
set and apply it right after the inline style declarations. Implement that
finally, to avoid mutating styles directly.

Test: svg/animations/attributeTypes.html

  • css/CSSStyleSelector.cpp: Model "SMIL animation style" applying just like "inline style" declarations.

(WebCore::CSSStyleSelector::addElementStyleProperties): Refactored common code from matchAllRules().
(WebCore::CSSStyleSelector::matchAllRules): Apply "SMIL animation style" after "inline style" declarations, as specified in SMIL2.

  • css/CSSStyleSelector.h: Add new addElementStyleProperties() helper.
  • svg/SVGAnimateElement.cpp: Keep track of animation state, if it's about to end, clear "SMIL animation style" upon next applyResultToTarget() call.

(WebCore::SVGAnimateElement::SVGAnimateElement):
(WebCore::SVGAnimateElement::applyResultsToTarget): Reset the CSS property we're animating int the "SMIL animation style", after animation ends.

(Instead of resetting target->style() properties to the old baseValue, as we used to do).

(WebCore::SVGAnimateElement::endedActiveInterval): Set m_aboutToStopAnimation to true, so next call to applyResultsToTarget() knows the animation ends.

  • svg/SVGAnimateElement.h: Store bool m_aboutToSTopAnimation;
  • svg/SVGAnimationElement.cpp:

(WebCore::setTargetAttributeAnimatedCSSValue):
(WebCore::setTargetAttributeAnimatedXMLValue):

Refactored both of these methods from setTargetAttributeAnimatedValue().
Changed the CSS part, to apply property changes to the "SMIL animation style" instead of the regular StylePropertySet.

(WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue): Refactored code, use shouldApplyAnimation() to determine whether this animation should run.
(WebCore::SVGAnimationElement::resetAnimationState): New helper calling setTargetAttributeAnimatedValue with a null-string for CSS attributes, when the animation ends.

This is used to detect that the CSS property should be removed from the "SMIL animation style".

(WebCore::SVGAnimationElement::shouldApplyAnimation): Refactored from existing code, and make it more obvious how attributeType influences the animation, all according to SVG 1.1/SMIL2.

  • svg/SVGAnimationElement.h:
  • svg/SVGElement.cpp: Manage the "SMIL animation style", in SVGElementRareData, if needed. Only gets created if SMIL animations on CSS properties run.

(WebCore::SVGElement::~SVGElement): Destroy SMIL animation style, upon destruction.
(WebCore::SVGElement::animatedSMILStyleProperties): Returns the StylePropertySet for the "SMIL animation style", if it's available.
(WebCore::SVGElement::ensureAnimatedSMILStyleProperties): Enforces creating the StylePropertySet for the "SMIL animation style".

  • svg/SVGElement.h: Expose new methods.
  • svg/SVGElementRareData.h: Stores the "SMIL animation style", actual managment is done by SVGElement, if needed.

(WebCore::SVGElementRareData::animatedSMILStyleProperties): Retrieve it.
(WebCore::SVGElementRareData::ensureAnimatedSMILStyleProperties): Create it.
(WebCore::SVGElementRareData::destroyAnimatedSMILStyleProperties): Destroy it.

  • svg/animation/SVGSMILElement.h: Make endedActiveInterval() virtual again, its needed by SVGAnimateElement now.

LayoutTests:

SVG CSS property animations aren't leaked into the DOM anymore, update the tests.

  • svg/animations/animate-color-transparent-expected.txt:
  • svg/animations/animate-currentColor-expected.txt:
  • svg/animations/animate-dynamic-update-attributeName-expected.txt:
  • svg/animations/animate-inherit-css-property-expected.txt:
  • svg/animations/attributeTypes-expected.txt: Added.
  • svg/animations/attributeTypes.html: Added.
  • svg/animations/resources/attributeTypes.svg: Added.
  • svg/animations/script-tests/animate-color-transparent.js:

(expectTransparent):
(expectOtherColor):

  • svg/animations/script-tests/animate-currentColor.js:

(sample1):
(sample2):
(sample3):

  • svg/animations/script-tests/animate-dynamic-update-attributeName.js:

(sample1):
(sample3):

  • svg/animations/script-tests/animate-inherit-css-property.js:

(sample1):
(sample2):
(sample3):

  • svg/animations/script-tests/attributeTypes.js: Added.

(sample1):
(sample2):
(sample3):
(executeTest):

  • svg/animations/script-tests/svgstring-animation-fallback-to-discrete.js:

(sample1):
(sample2):
(sample3):

  • svg/animations/svgstring-animation-fallback-to-discrete-expected.txt:
Location:
trunk
Files:
4 added
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r109334 r109342  
     12012-03-01  Nikolas Zimmermann  <nzimmermann@rim.com>
     2
     3        Introduce SMIL overrideStyle, to make SVG stop mutating CSS styles directly
     4        https://bugs.webkit.org/show_bug.cgi?id=79790
     5
     6        Reviewed by Zoltan Herczeg.
     7
     8        SVG CSS property animations aren't leaked into the DOM anymore, update the tests.
     9
     10        * svg/animations/animate-color-transparent-expected.txt:
     11        * svg/animations/animate-currentColor-expected.txt:
     12        * svg/animations/animate-dynamic-update-attributeName-expected.txt:
     13        * svg/animations/animate-inherit-css-property-expected.txt:
     14        * svg/animations/attributeTypes-expected.txt: Added.
     15        * svg/animations/attributeTypes.html: Added.
     16        * svg/animations/resources/attributeTypes.svg: Added.
     17        * svg/animations/script-tests/animate-color-transparent.js:
     18        (expectTransparent):
     19        (expectOtherColor):
     20        * svg/animations/script-tests/animate-currentColor.js:
     21        (sample1):
     22        (sample2):
     23        (sample3):
     24        * svg/animations/script-tests/animate-dynamic-update-attributeName.js:
     25        (sample1):
     26        (sample3):
     27        * svg/animations/script-tests/animate-inherit-css-property.js:
     28        (sample1):
     29        (sample2):
     30        (sample3):
     31        * svg/animations/script-tests/attributeTypes.js: Added.
     32        (sample1):
     33        (sample2):
     34        (sample3):
     35        (executeTest):
     36        * svg/animations/script-tests/svgstring-animation-fallback-to-discrete.js:
     37        (sample1):
     38        (sample2):
     39        (sample3):
     40        * svg/animations/svgstring-animation-fallback-to-discrete-expected.txt:
     41
    1422012-03-01  Florin Malita  <fmalita@google.com>
    243
  • trunk/LayoutTests/svg/animations/animate-color-transparent-expected.txt

    r79675 r109342  
    66
    77
    8 PASS rect.style.fill is '#00ff00'
    9 PASS rect.style.fill is '#7f0000'
     8PASS getComputedStyle(rect).fill is '#00ff00'
     9PASS rect.style.fill is ""
     10PASS getComputedStyle(rect).fill is '#7f0000'
     11PASS rect.style.fill is ""
    1012PASS successfullyParsed is true
    1113
  • trunk/LayoutTests/svg/animations/animate-currentColor-expected.txt

    r79675 r109342  
    66
    77
    8 PASS rect.style.fill is '#ff0000'
    9 PASS rect.style.fill is '#804000'
    10 PASS rect.style.fill is '#008000'
     8PASS getComputedStyle(rect).fill is '#ff0000'
     9PASS rect.style.fill is ""
     10PASS getComputedStyle(rect).fill is '#804000'
     11PASS rect.style.fill is ""
     12PASS getComputedStyle(rect).fill is '#008000'
     13PASS rect.style.fill is ""
    1114PASS successfullyParsed is true
    1215
  • trunk/LayoutTests/svg/animations/animate-dynamic-update-attributeName-expected.txt

    r84999 r109342  
    66
    77
    8 PASS rect.style.color is 'rgb(0, 128, 0)'
    9 PASS rect.style.fill is '#008000'
     8PASS getComputedStyle(rect).color is 'rgb(0, 128, 0)'
     9PASS rect.style.color is ""
     10PASS getComputedStyle(rect).fill is '#008000'
     11PASS rect.style.fill is ""
    1012PASS successfullyParsed is true
    1113
  • trunk/LayoutTests/svg/animations/animate-inherit-css-property-expected.txt

    r79675 r109342  
    66
    77
    8 PASS rect.style.fill is '#ff0000'
    9 PASS rect.style.fill is '#804000'
    10 PASS rect.style.fill is '#008000'
     8PASS getComputedStyle(rect).fill is '#ff0000'
     9PASS rect.style.fill is ""
     10PASS getComputedStyle(rect).fill is '#804000'
     11PASS rect.style.fill is ""
     12PASS getComputedStyle(rect).fill is '#008000'
     13PASS rect.style.fill is ""
    1114PASS successfullyParsed is true
    1215
  • trunk/LayoutTests/svg/animations/script-tests/animate-color-transparent.js

    r107682 r109342  
    2222// Setup animation test
    2323function expectTransparent() {
    24     shouldBe("rect.style.fill", "'#00ff00'");
     24    shouldBe("getComputedStyle(rect).fill", "'#00ff00'");
     25    shouldBeEqualToString("rect.style.fill", "");
    2526}
    2627
    2728function expectOtherColor() {
    28     shouldBe("rect.style.fill", "'#7f0000'");
     29    shouldBe("getComputedStyle(rect).fill", "'#7f0000'");
     30    shouldBeEqualToString("rect.style.fill", "");
    2931}
    3032
  • trunk/LayoutTests/svg/animations/script-tests/animate-currentColor.js

    r107682 r109342  
    2525function sample1() {
    2626    // Check initial/end conditions
    27     shouldBe("rect.style.fill", "'#ff0000'");
     27    shouldBe("getComputedStyle(rect).fill", "'#ff0000'");
     28    shouldBeEqualToString("rect.style.fill", "");
    2829}
    2930
    3031function sample2() {
    3132    // Check half-time conditions
    32     shouldBe("rect.style.fill", "'#804000'");
     33    shouldBe("getComputedStyle(rect).fill", "'#804000'");
     34    shouldBeEqualToString("rect.style.fill", "");
    3335}
    3436
    3537function sample3() {
    3638    // Check half-time conditions
    37     shouldBe("rect.style.fill", "'#008000'");
     39    shouldBe("getComputedStyle(rect).fill", "'#008000'");
     40    shouldBeEqualToString("rect.style.fill", "");
    3841}
    3942
  • trunk/LayoutTests/svg/animations/script-tests/animate-dynamic-update-attributeName.js

    r107791 r109342  
    2525// Setup animation test
    2626function sample1() {
    27     shouldBe("rect.style.color", "'rgb(0, 128, 0)'");
     27    shouldBe("getComputedStyle(rect).color", "'rgb(0, 128, 0)'");
     28    shouldBeEqualToString("rect.style.color", "");
    2829}
    2930
     
    3435
    3536function sample3() {
    36     shouldBe("rect.style.fill", "'#008000'");
     37    shouldBe("getComputedStyle(rect).fill", "'#008000'");
     38    shouldBeEqualToString("rect.style.fill", "");
    3739}
    3840
  • trunk/LayoutTests/svg/animations/script-tests/animate-inherit-css-property.js

    r107682 r109342  
    2828function sample1() {
    2929    // Check initial/end conditions
    30     shouldBe("rect.style.fill", "'#ff0000'");
     30    shouldBe("getComputedStyle(rect).fill", "'#ff0000'");
     31    shouldBeEqualToString("rect.style.fill", "");
    3132}
    3233
    3334function sample2() {
    3435    // Check half-time conditions
    35     shouldBe("rect.style.fill", "'#804000'");
     36    shouldBe("getComputedStyle(rect).fill", "'#804000'");
     37    shouldBeEqualToString("rect.style.fill", "");
    3638}
    3739
    3840function sample3() {
    3941    // Check half-time conditions
    40     shouldBe("rect.style.fill", "'#008000'");
     42    shouldBe("getComputedStyle(rect).fill", "'#008000'");
     43    shouldBeEqualToString("rect.style.fill", "");
    4144}
    4245
  • trunk/LayoutTests/svg/animations/script-tests/svgstring-animation-fallback-to-discrete.js

    r107682 r109342  
    2323function sample1() {
    2424    // Check initial/end conditions
    25     shouldBe("rect.style.visibility", "'visible'");
     25    shouldBe("getComputedStyle(rect).visibility", "'visible'");
     26    shouldBeEqualToString("rect.style.visibility", "");
    2627}
    2728
    2829function sample2() {
    29     shouldBe("rect.style.visibility", "'hidden'");
     30    shouldBe("getComputedStyle(rect).visibility", "'hidden'");
     31    shouldBeEqualToString("rect.style.visibility", "");
    3032}
    3133
    3234function sample3() {
    33     shouldBe("rect.style.visibility", "'visible'");
     35    shouldBe("getComputedStyle(rect).visibility", "'visible'");
     36    shouldBeEqualToString("rect.style.visibility", "");
    3437}
    3538
  • trunk/LayoutTests/svg/animations/svgstring-animation-fallback-to-discrete-expected.txt

    r107682 r109342  
    66
    77
    8 PASS rect.style.visibility is 'visible'
    9 PASS rect.style.visibility is 'hidden'
    10 PASS rect.style.visibility is 'visible'
    11 PASS rect.style.visibility is 'visible'
     8PASS getComputedStyle(rect).visibility is 'visible'
     9PASS rect.style.visibility is ""
     10PASS getComputedStyle(rect).visibility is 'hidden'
     11PASS rect.style.visibility is ""
     12PASS getComputedStyle(rect).visibility is 'visible'
     13PASS rect.style.visibility is ""
     14PASS getComputedStyle(rect).visibility is 'visible'
     15PASS rect.style.visibility is ""
    1216PASS successfullyParsed is true
    1317
  • trunk/Source/WebCore/ChangeLog

    r109340 r109342  
     12012-03-01  Nikolas Zimmermann  <nzimmermann@rim.com>
     2
     3        Introduce SMIL overrideStyle, to make SVG stop mutating CSS styles directly
     4        https://bugs.webkit.org/show_bug.cgi?id=79790
     5
     6        Reviewed by Zoltan Herczeg.
     7
     8        Next step towards enabling animVal support for XML attribute animations.
     9        When SVG CSS properties are animated using SMIL, we currently mutate
     10        the target elements style, and have to keep a baseValue around as String
     11        to be able to recover from the DOM mutations at the end, if fill!="freeze".
     12
     13        The approach required by SMIL is to keep around an override style declaration
     14        set and apply it right after the inline style declarations. Implement that
     15        finally, to avoid mutating styles directly.
     16
     17        Test: svg/animations/attributeTypes.html
     18
     19        * css/CSSStyleSelector.cpp: Model "SMIL animation style" applying just like "inline style" declarations.
     20        (WebCore::CSSStyleSelector::addElementStyleProperties): Refactored common code from matchAllRules().
     21        (WebCore::CSSStyleSelector::matchAllRules): Apply "SMIL animation style" after "inline style" declarations, as specified in SMIL2.
     22        * css/CSSStyleSelector.h: Add new addElementStyleProperties() helper.
     23        * svg/SVGAnimateElement.cpp: Keep track of animation state, if it's about to end, clear "SMIL animation style" upon next applyResultToTarget() call.
     24        (WebCore::SVGAnimateElement::SVGAnimateElement):
     25        (WebCore::SVGAnimateElement::applyResultsToTarget): Reset the CSS property we're animating int the "SMIL animation style", after animation ends.
     26                                                            (Instead of resetting target->style() properties to the old baseValue, as we used to do).
     27        (WebCore::SVGAnimateElement::endedActiveInterval): Set m_aboutToStopAnimation to true, so next call to applyResultsToTarget() knows the animation ends.
     28        * svg/SVGAnimateElement.h: Store bool m_aboutToSTopAnimation;
     29        * svg/SVGAnimationElement.cpp:
     30        (WebCore::setTargetAttributeAnimatedCSSValue):
     31        (WebCore::setTargetAttributeAnimatedXMLValue):
     32            Refactored both of these methods from setTargetAttributeAnimatedValue().
     33            Changed the CSS part, to apply property changes to the "SMIL animation style" instead of the regular StylePropertySet.
     34        (WebCore::SVGAnimationElement::setTargetAttributeAnimatedValue): Refactored code, use shouldApplyAnimation() to determine whether this animation should run.
     35        (WebCore::SVGAnimationElement::resetAnimationState): New helper calling setTargetAttributeAnimatedValue with a null-string for CSS attributes, when the animation ends.
     36                                                             This is used to detect that the CSS property should be removed from the "SMIL animation style".
     37        (WebCore::SVGAnimationElement::shouldApplyAnimation): Refactored from existing code, and make it more obvious how attributeType influences the animation, all according to SVG 1.1/SMIL2.
     38        * svg/SVGAnimationElement.h:
     39        * svg/SVGElement.cpp: Manage the "SMIL animation style", in SVGElementRareData, if needed. Only gets created if SMIL animations on CSS properties run.
     40        (WebCore::SVGElement::~SVGElement): Destroy SMIL animation style, upon destruction.
     41        (WebCore::SVGElement::animatedSMILStyleProperties): Returns the StylePropertySet for the "SMIL animation style", if it's available.
     42        (WebCore::SVGElement::ensureAnimatedSMILStyleProperties): Enforces creating the StylePropertySet for the "SMIL animation style".
     43        * svg/SVGElement.h: Expose new methods.
     44        * svg/SVGElementRareData.h: Stores the "SMIL animation style", actual managment is done by SVGElement, if needed.
     45        (WebCore::SVGElementRareData::animatedSMILStyleProperties): Retrieve it.
     46        (WebCore::SVGElementRareData::ensureAnimatedSMILStyleProperties): Create it.
     47        (WebCore::SVGElementRareData::destroyAnimatedSMILStyleProperties): Destroy it.
     48        * svg/animation/SVGSMILElement.h: Make endedActiveInterval() virtual again, its needed by SVGAnimateElement now.
     49
    1502012-03-01  Nikolas Zimmermann  <nzimmermann@rim.com>
    251
  • trunk/Source/WebCore/css/CSSStyleSelector.cpp

    r109331 r109342  
    123123
    124124#if ENABLE(SVG)
     125#include "SVGElement.h"
    125126#include "SVGNames.h"
    126127#endif
     
    764765}
    765766
     767inline void CSSStyleSelector::addElementStyleProperties(MatchResult& result, StylePropertySet* propertySet, bool isCacheable)
     768{
     769    if (!propertySet)
     770        return;
     771    result.ranges.lastAuthorRule = result.matchedProperties.size();
     772    if (result.ranges.firstAuthorRule == -1)
     773        result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
     774    addMatchedProperties(result, propertySet);
     775    if (!isCacheable)
     776        result.isCacheable = false;
     777}
     778
    766779void CSSStyleSelector::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
    767780{
     
    10341047    // Now check author rules, beginning first with presentational attributes mapped from HTML.
    10351048    if (m_styledElement) {
    1036         if (StylePropertySet* attributeStyle = m_styledElement->attributeStyle()) {
    1037             result.ranges.lastAuthorRule = m_matchedRules.size();
    1038             if (result.ranges.firstAuthorRule == -1)
    1039                 result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
    1040             addMatchedProperties(result, attributeStyle);
    1041         }
     1049        addElementStyleProperties(result, m_styledElement->attributeStyle());
    10421050
    10431051        // Now we check additional mapped declarations.
    10441052        // Tables and table cells share an additional mapped rule that must be applied
    10451053        // after all attributes, since their mapped style depends on the values of multiple attributes.
    1046         if (StylePropertySet* additionalStyle = m_styledElement->additionalAttributeStyle()) {
    1047             if (result.ranges.firstAuthorRule == -1)
    1048                 result.ranges.firstAuthorRule = result.matchedProperties.size();
    1049             result.ranges.lastAuthorRule = result.ranges.firstAuthorRule;
    1050             addMatchedProperties(result, additionalStyle);
    1051         }
     1054        addElementStyleProperties(result, m_styledElement->additionalAttributeStyle());
    10521055
    10531056        if (m_styledElement->isHTMLElement()) {
     
    10641067
    10651068    // Now check our inline style attribute.
    1066     if (m_matchAuthorAndUserStyles && m_styledElement) {
    1067         StylePropertySet* inlineDecl = m_styledElement->inlineStyleDecl();
    1068         if (inlineDecl) {
    1069             result.ranges.lastAuthorRule = result.matchedProperties.size();
    1070             if (result.ranges.firstAuthorRule == -1)
    1071                 result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
    1072             addMatchedProperties(result, inlineDecl);
    1073             result.isCacheable = false;
    1074         }
    1075     }
     1069    if (m_matchAuthorAndUserStyles && m_styledElement)
     1070        addElementStyleProperties(result, m_styledElement->inlineStyleDecl(), false /* isCacheable */);
     1071
     1072#if ENABLE(SVG)
     1073    // Now check SMIL animation override style.
     1074    if (m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->isSVGElement())
     1075        addElementStyleProperties(result, static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties(), false /* isCacheable */);
     1076#endif
    10761077}
    10771078
     
    11291130    if (p->inlineStyleDecl())
    11301131        return 0;
     1132#if ENABLE(SVG)
     1133    if (p->isSVGElement() && static_cast<SVGElement*>(p)->animatedSMILStyleProperties())
     1134        return 0;
     1135#endif
    11311136    if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
    11321137        return 0;
     
    12771282    if (element->inlineStyleDecl())
    12781283        return false;
     1284#if ENABLE(SVG)
     1285    if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
     1286        return false;
     1287#endif
    12791288    if (!!element->attributeStyle() != !!m_styledElement->attributeStyle())
    12801289        return false;
     
    13741383    if (m_styledElement->inlineStyleDecl())
    13751384        return 0;
     1385#if ENABLE(SVG)
     1386    if (m_styledElement->isSVGElement() && static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties())
     1387        return 0;
     1388#endif
    13761389    // Ids stop style sharing if they show up in the stylesheets.
    13771390    if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
  • trunk/Source/WebCore/css/CSSStyleSelector.h

    r109227 r109342  
    296296
    297297    static void addMatchedProperties(MatchResult&, StylePropertySet* properties, StyleRule* = 0, unsigned linkMatchType = SelectorChecker::MatchAll, bool inRegionRule = false);
     298    void addElementStyleProperties(MatchResult&, StylePropertySet*, bool isCacheable = true);
    298299
    299300    void matchAllRules(MatchResult&);
  • trunk/Source/WebCore/svg/SVGAnimateElement.cpp

    r108134 r109342  
    4242    : SVGAnimationElement(tagName, document)
    4343    , m_animatedPropertyType(AnimatedString)
     44    , m_aboutToStopAnimation(false)
    4445    , m_fromPropertyValueType(RegularPropertyValue)
    4546    , m_toPropertyValueType(RegularPropertyValue)
     
    231232    ASSERT(m_animatedType);
    232233
     234    if (m_aboutToStopAnimation) {
     235        m_aboutToStopAnimation = false;
     236        resetAnimationState(m_animatedType->valueAsString());
     237        return;
     238    }
     239
    233240    setTargetAttributeAnimatedValue(m_animatedType->valueAsString());
    234241}
     
    261268}
    262269
     270void SVGAnimateElement::endedActiveInterval()
     271{
     272    SVGAnimationElement::endedActiveInterval();
     273    m_aboutToStopAnimation = true;
     274}
     275
    263276}
    264277#endif // ENABLE(SVG)
  • trunk/Source/WebCore/svg/SVGAnimateElement.h

    r108134 r109342  
    6666    virtual float calculateDistance(const String& fromString, const String& toString);
    6767
     68    virtual void endedActiveInterval();
    6869    virtual void targetElementDidChange(SVGElement* targetElement) OVERRIDE;
    6970
     
    7374    virtual bool hasValidAttributeType();
    7475    AnimatedPropertyType m_animatedPropertyType;
     76    bool m_aboutToStopAnimation;
    7577
    7678    AnimatedPropertyValueType m_fromPropertyValueType;
  • trunk/Source/WebCore/svg/SVGAnimationElement.cpp

    r107693 r109342  
    331331}
    332332
     333static inline void setTargetAttributeAnimatedCSSValue(SVGElement* targetElement, const QualifiedName& attributeName, const String& value)
     334{
     335    StylePropertySet* propertySet = targetElement->ensureAnimatedSMILStyleProperties();
     336    if (value.isNull()) {
     337        if (propertySet->removeProperty(cssPropertyID(attributeName.localName())))
     338            targetElement->setNeedsStyleRecalc();
     339        return;
     340    }
     341
     342    if (propertySet->setProperty(cssPropertyID(attributeName.localName()), value, false, 0))
     343        targetElement->setNeedsStyleRecalc();
     344}
     345
     346static inline void setTargetAttributeAnimatedXMLValue(SVGElement* targetElement, const QualifiedName& attributeName, const String& value)
     347{
     348    // FIXME: Detach animVal, if value.isNull() - once animVal support is enabled.
     349    targetElement->setAttribute(attributeName, value);
     350}
     351
    333352void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value)
    334353{
    335     if (!hasValidAttributeType())
    336         return;
    337354    SVGElement* targetElement = this->targetElement();
    338     QualifiedName attributeName = this->attributeName();
    339     if (!targetElement || attributeName == anyQName() || value.isNull())
    340         return;
    341 
    342     // We don't want the instance tree to get rebuild. Instances are updated in the loop below.
     355    const QualifiedName& attributeName = this->attributeName();
     356    ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
     357    if (shouldApply == DontApplyAnimation)
     358        return;
     359
     360    if (shouldApply == ApplyCSSAnimation)
     361        setTargetAttributeAnimatedCSSValue(targetElement, attributeName, value);
     362    else
     363        setTargetAttributeAnimatedXMLValue(targetElement, attributeName, value);
     364
    343365    if (targetElement->isStyled())
    344366        static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(true);
    345        
    346     bool attributeIsCSSProperty = isTargetAttributeCSSProperty(targetElement, attributeName);
    347     // Stop animation, if attributeType is set to CSS by the user, but the attribute itself is not a CSS property.
    348     if (!attributeIsCSSProperty && attributeType() == AttributeTypeCSS)
    349         return;
    350 
    351     ExceptionCode ec;
    352     if (attributeIsCSSProperty) {
    353         // FIXME: This should set the override style, not the inline style.
    354         // Sadly override styles are not yet implemented.
    355         targetElement->style()->setProperty(attributeName.localName(), value, "", ec);
    356     } else {
    357         // FIXME: This should set the 'presentation' value, not the actual
    358         // attribute value. Whatever that means in practice.
    359         targetElement->setAttribute(attributeName, value);
    360     }
    361    
    362     if (targetElement->isStyled())
    363         static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(false);
    364    
    365     // If the target element is used in an <use> instance tree, update that as well.
     367
     368    // If the target element has instances, update them as well, w/o requiring the <use> tree to be rebuilt.
    366369    const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement();
    367370    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
     
    370373        if (!shadowTreeElement)
    371374            continue;
    372         if (attributeIsCSSProperty)
    373             shadowTreeElement->style()->setProperty(attributeName.localName(), value, "", ec);
     375
     376        if (shouldApply == ApplyCSSAnimation)
     377            setTargetAttributeAnimatedCSSValue(shadowTreeElement, attributeName, value);
    374378        else
    375             shadowTreeElement->setAttribute(attributeName, value);
    376         (*it)->correspondingUseElement()->setNeedsStyleRecalc();
    377     }
    378 }
    379    
     379            setTargetAttributeAnimatedCSSValue(shadowTreeElement, attributeName, value);
     380    }
     381
     382    if (targetElement->isStyled())
     383        static_cast<SVGStyledElement*>(targetElement)->setInstanceUpdatesBlocked(false);
     384}
     385
     386void SVGAnimationElement::resetAnimationState(const String& baseValue)
     387{
     388    // FIXME: This extra check will go away, once animVal is enabled.
     389    SVGElement* targetElement = this->targetElement();
     390    const QualifiedName& attributeName = this->attributeName();
     391    ShouldApplyAnimation shouldApply = shouldApplyAnimation(targetElement, attributeName);
     392    if (shouldApply == DontApplyAnimation)
     393        return;
     394
     395    if (isFrozen() || shouldApply == ApplyXMLAnimation)
     396        setTargetAttributeAnimatedValue(baseValue);
     397    else // Only CSS animations support detaching previously animated properties so far, indicating by passing a null-string.
     398        setTargetAttributeAnimatedValue(String());
     399}
     400
     401SVGAnimationElement::ShouldApplyAnimation SVGAnimationElement::shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName)
     402{
     403    if (!hasValidAttributeType() || !targetElement || attributeName == anyQName())
     404        return DontApplyAnimation;
     405
     406    AttributeType attributeType = this->attributeType();
     407    switch (attributeType) {
     408    case AttributeTypeAuto:
     409        // For attributeType="auto", try CSS first. If that fails, try XML.
     410    case AttributeTypeCSS:
     411        // If attributeName is a known animatable SVG CSS property, apply the animation.
     412        if (isTargetAttributeCSSProperty(targetElement, attributeName))
     413            return ApplyCSSAnimation;
     414        // If attributeName is unknown and ttributeType is not 'auto', don't apply the animation.
     415        if (attributeType == AttributeTypeCSS)
     416            return DontApplyAnimation;
     417        // For attributeType="auto", try XML animation now.
     418    case AttributeTypeXML:
     419        return ApplyXMLAnimation;
     420    };
     421
     422    ASSERT_NOT_REACHED();
     423    return DontApplyAnimation;
     424}
     425
    380426void SVGAnimationElement::calculateKeyTimesForCalcModePaced()
    381427{
     
    594640        m_animationValid = calcMode == CalcModePaced || !fastHasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size());
    595641}
    596    
     642
    597643void SVGAnimationElement::updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement)
    598644{   
  • trunk/Source/WebCore/svg/SVGAnimationElement.h

    r107693 r109342  
    106106    virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement);
    107107
     108    void resetAnimationState(const String& baseValue);
     109
    108110private:
    109111    virtual void attributeChanged(Attribute*) OVERRIDE;
     
    122124    float calculatePercentForFromTo(float percent) const;
    123125    unsigned calculateKeyTimesIndex(float percent) const;
     126
     127    enum ShouldApplyAnimation {
     128        DontApplyAnimation,
     129        ApplyCSSAnimation,
     130        ApplyXMLAnimation
     131    };
     132
     133    ShouldApplyAnimation shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName);
    124134
    125135    BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGAnimationElement)
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r109097 r109342  
    7979
    8080        SVGElementRareData* rareData = it->second;
     81        rareData->destroyAnimatedSMILStyleProperties();
    8182        if (SVGCursorElement* cursorElement = rareData->cursorElement())
    8283            cursorElement->removeClient(this);
     
    487488
    488489    return document()->styleSelector()->styleForElement(correspondingElement(), style, false /*allowSharing*/);
     490}
     491
     492StylePropertySet* SVGElement::animatedSMILStyleProperties() const
     493{
     494    if (hasRareSVGData())
     495        return rareSVGData()->animatedSMILStyleProperties();
     496    return 0;
     497}
     498
     499StylePropertySet* SVGElement::ensureAnimatedSMILStyleProperties()
     500{
     501    return ensureRareSVGData()->ensureAnimatedSMILStyleProperties();
    489502}
    490503
  • trunk/Source/WebCore/svg/SVGElement.h

    r108758 r109342  
    108108#endif
    109109
     110    StylePropertySet* animatedSMILStyleProperties() const;
     111    StylePropertySet* ensureAnimatedSMILStyleProperties();
     112
    110113protected:
    111114    SVGElement(const QualifiedName&, Document*, ConstructionType = CreateSVGElement);
  • trunk/Source/WebCore/svg/SVGElementRareData.h

    r95901 r109342  
    7575    void setCursorImageValue(CSSCursorImageValue* cursorImageValue) { m_cursorImageValue = cursorImageValue; }
    7676
     77    StylePropertySet* animatedSMILStyleProperties() const { return m_animatedSMILStyleProperties.get(); }
     78    StylePropertySet* ensureAnimatedSMILStyleProperties()
     79    {
     80        if (!m_animatedSMILStyleProperties) {
     81            m_animatedSMILStyleProperties = StylePropertySet::create();
     82            m_animatedSMILStyleProperties->setStrictParsing(false);
     83        }
     84        return m_animatedSMILStyleProperties.get();
     85    }
     86
     87    void destroyAnimatedSMILStyleProperties()
     88    {
     89        m_animatedSMILStyleProperties.clear();
     90    }
     91
    7792private:
    7893    HashSet<SVGElementInstance*> m_elementInstances;
     
    8297    bool m_instancesUpdatesBlocked : 1;
    8398    bool m_hasPendingResources : 1;
     99    RefPtr<StylePropertySet> m_animatedSMILStyleProperties;
    84100};
    85101
  • trunk/Source/WebCore/svg/animation/SVGSMILElement.h

    r108134 r109342  
    117117    // Sub-classes may need to take action when the target is changed.
    118118    virtual void targetElementDidChange(SVGElement*) { }
     119    virtual void endedActiveInterval();
    119120
    120121private:
    121122    virtual void startedActiveInterval() = 0;
    122123    virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
    123     void endedActiveInterval();
    124124
    125125    enum BeginOrEnd {
Note: See TracChangeset for help on using the changeset viewer.