Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2007 Eric Seidel <eric (at) webkit.org>
      5  * Copyright (C) 2008 Apple Inc. All rights reserved.
      6  * Copyright (C) 2008 Cameron McCormack <cam (at) mcc.id.au>
      7  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #ifndef SVGAnimationElement_h
     26 #define SVGAnimationElement_h
     27 
     28 #include "core/platform/graphics/UnitBezier.h"
     29 #include "core/svg/SVGAnimatedBoolean.h"
     30 #include "core/svg/SVGExternalResourcesRequired.h"
     31 #include "core/svg/SVGTests.h"
     32 #include "core/svg/animation/SVGSMILElement.h"
     33 
     34 namespace WebCore {
     35 
     36 enum AnimationMode {
     37     NoAnimation,
     38     FromToAnimation,
     39     FromByAnimation,
     40     ToAnimation,
     41     ByAnimation,
     42     ValuesAnimation,
     43     PathAnimation // Used by AnimateMotion.
     44 };
     45 
     46 // If we have 'currentColor' or 'inherit' as animation value, we need to grab
     47 // the value during the animation since the value can be animated itself.
     48 enum AnimatedPropertyValueType {
     49     RegularPropertyValue,
     50     CurrentColorValue,
     51     InheritValue
     52 };
     53 
     54 enum CalcMode {
     55     CalcModeDiscrete,
     56     CalcModeLinear,
     57     CalcModePaced,
     58     CalcModeSpline
     59 };
     60 
     61 class ConditionEventListener;
     62 class TimeContainer;
     63 class SVGAnimatedType;
     64 
     65 class SVGAnimationElement : public SVGSMILElement,
     66                             public SVGTests,
     67                             public SVGExternalResourcesRequired {
     68 public:
     69     // SVGAnimationElement
     70     float getStartTime() const;
     71     float getCurrentTime() const;
     72     float getSimpleDuration() const;
     73 
     74     void beginElement();
     75     void beginElementAt(float offset);
     76     void endElement();
     77     void endElementAt(float offset);
     78 
     79     static bool isTargetAttributeCSSProperty(SVGElement*, const QualifiedName&);
     80 
     81     virtual bool isAdditive() const;
     82     bool isAccumulated() const;
     83     AnimationMode animationMode() const { return m_animationMode; }
     84     CalcMode calcMode() const { return m_calcMode; }
     85 
     86     enum ShouldApplyAnimation {
     87         DontApplyAnimation,
     88         ApplyCSSAnimation,
     89         ApplyXMLAnimation
     90     };
     91 
     92     ShouldApplyAnimation shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName);
     93 
     94     AnimatedPropertyValueType fromPropertyValueType() const { return m_fromPropertyValueType; }
     95     AnimatedPropertyValueType toPropertyValueType() const { return m_toPropertyValueType; }
     96 
     97     template<typename AnimatedType>
     98     void adjustForInheritance(AnimatedType (*parseTypeFromString)(SVGAnimationElement*, const String&),
     99                               AnimatedPropertyValueType valueType, AnimatedType& animatedType, SVGElement* contextElement)
    100     {
    101         if (valueType != InheritValue)
    102             return;
    103         // Replace 'inherit' by its computed property value.
    104         ASSERT(parseTypeFromString);
    105         String typeString;
    106         adjustForInheritance(contextElement, attributeName(), typeString);
    107         animatedType = (*parseTypeFromString)(this, typeString);
    108     }
    109 
    110     template<typename AnimatedType>
    111     bool adjustFromToListValues(const AnimatedType& fromList, const AnimatedType& toList, AnimatedType& animatedList, float percentage, bool resizeAnimatedListIfNeeded = true)
    112     {
    113         // If no 'to' value is given, nothing to animate.
    114         unsigned toListSize = toList.size();
    115         if (!toListSize)
    116             return false;
    117 
    118         // If the 'from' value is given and it's length doesn't match the 'to' value list length, fallback to a discrete animation.
    119         unsigned fromListSize = fromList.size();
    120         if (fromListSize != toListSize && fromListSize) {
    121             if (percentage < 0.5) {
    122                 if (animationMode() != ToAnimation)
    123                     animatedList = AnimatedType(fromList);
    124             } else
    125                 animatedList = AnimatedType(toList);
    126 
    127             return false;
    128         }
    129 
    130         ASSERT(!fromListSize || fromListSize == toListSize);
    131         if (resizeAnimatedListIfNeeded && animatedList.size() < toListSize)
    132             animatedList.resize(toListSize);
    133 
    134         return true;
    135     }
    136 
    137     template<typename AnimatedType>
    138     void animateDiscreteType(float percentage, const AnimatedType& fromType, const AnimatedType& toType, AnimatedType& animatedType)
    139     {
    140         if ((animationMode() == FromToAnimation && percentage > 0.5) || animationMode() == ToAnimation || percentage == 1) {
    141             animatedType = AnimatedType(toType);
    142             return;
    143         }
    144         animatedType = AnimatedType(fromType);
    145     }
    146 
    147     void animateAdditiveNumber(float percentage, unsigned repeatCount, float fromNumber, float toNumber, float toAtEndOfDurationNumber, float& animatedNumber)
    148     {
    149         float number;
    150         if (calcMode() == CalcModeDiscrete)
    151             number = percentage < 0.5 ? fromNumber : toNumber;
    152         else
    153             number = (toNumber - fromNumber) * percentage + fromNumber;
    154 
    155         if (isAccumulated() && repeatCount)
    156             number += toAtEndOfDurationNumber * repeatCount;
    157 
    158         if (isAdditive() && animationMode() != ToAnimation)
    159             animatedNumber += number;
    160         else
    161             animatedNumber = number;
    162     }
    163 
    164 protected:
    165     SVGAnimationElement(const QualifiedName&, Document*);
    166 
    167     void computeCSSPropertyValue(SVGElement*, CSSPropertyID, String& value);
    168     virtual void determinePropertyValueTypes(const String& from, const String& to);
    169 
    170     bool isSupportedAttribute(const QualifiedName&);
    171     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
    172     virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
    173 
    174     enum AttributeType {
    175         AttributeTypeCSS,
    176         AttributeTypeXML,
    177         AttributeTypeAuto
    178     };
    179     AttributeType attributeType() const { return m_attributeType; }
    180 
    181     String toValue() const;
    182     String byValue() const;
    183     String fromValue() const;
    184 
    185     String targetAttributeBaseValue();
    186 
    187     // from SVGSMILElement
    188     virtual void startedActiveInterval() OVERRIDE;
    189     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) OVERRIDE;
    190 
    191     AnimatedPropertyValueType m_fromPropertyValueType;
    192     AnimatedPropertyValueType m_toPropertyValueType;
    193 
    194     virtual void setTargetElement(SVGElement*) OVERRIDE;
    195     virtual void setAttributeName(const QualifiedName&) OVERRIDE;
    196     bool hasInvalidCSSAttributeType() const { return m_hasInvalidCSSAttributeType; }
    197 
    198     virtual void updateAnimationMode();
    199     void setAnimationMode(AnimationMode animationMode) { m_animationMode = animationMode; }
    200     void setCalcMode(CalcMode calcMode) { m_calcMode = calcMode; }
    201 
    202 private:
    203     virtual void animationAttributeChanged() OVERRIDE;
    204     void setAttributeType(const AtomicString&);
    205 
    206     void checkInvalidCSSAttributeType(SVGElement*);
    207 
    208     virtual bool calculateToAtEndOfDurationValue(const String& toAtEndOfDurationString) = 0;
    209     virtual bool calculateFromAndToValues(const String& fromString, const String& toString) = 0;
    210     virtual bool calculateFromAndByValues(const String& fromString, const String& byString) = 0;
    211     virtual void calculateAnimatedValue(float percent, unsigned repeatCount, SVGSMILElement* resultElement) = 0;
    212     virtual float calculateDistance(const String& /*fromString*/, const String& /*toString*/) { return -1.f; }
    213 
    214     void currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to);
    215     void calculateKeyTimesForCalcModePaced();
    216     float calculatePercentFromKeyPoints(float percent) const;
    217     void currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const;
    218     float calculatePercentForSpline(float percent, unsigned splineIndex) const;
    219     float calculatePercentForFromTo(float percent) const;
    220     unsigned calculateKeyTimesIndex(float percent) const;
    221 
    222     void applyAnimatedValue(ShouldApplyAnimation, SVGElement* targetElement, const QualifiedName& attributeName, SVGAnimatedType*);
    223     void adjustForInheritance(SVGElement* targetElement, const QualifiedName& attributeName, String&);
    224 
    225     BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGAnimationElement)
    226         DECLARE_ANIMATED_BOOLEAN(ExternalResourcesRequired, externalResourcesRequired)
    227     END_DECLARE_ANIMATED_PROPERTIES
    228 
    229     // SVGTests
    230     virtual void synchronizeRequiredFeatures() { SVGTests::synchronizeRequiredFeatures(this); }
    231     virtual void synchronizeRequiredExtensions() { SVGTests::synchronizeRequiredExtensions(this); }
    232     virtual void synchronizeSystemLanguage() { SVGTests::synchronizeSystemLanguage(this); }
    233 
    234     void setCalcMode(const AtomicString&);
    235 
    236     bool m_animationValid;
    237 
    238     AttributeType m_attributeType;
    239     Vector<String> m_values;
    240     Vector<float> m_keyTimes;
    241     Vector<float> m_keyPoints;
    242     Vector<UnitBezier> m_keySplines;
    243     String m_lastValuesAnimationFrom;
    244     String m_lastValuesAnimationTo;
    245     bool m_hasInvalidCSSAttributeType;
    246     CalcMode m_calcMode;
    247     AnimationMode m_animationMode;
    248 };
    249 
    250 } // namespace WebCore
    251 
    252 #endif // SVGAnimationElement_h
    253