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/svg/SVGAnimatedBoolean.h"
     29 #include "core/svg/animation/SVGSMILElement.h"
     30 #include "platform/animation/UnitBezier.h"
     31 #include "wtf/Functional.h"
     32 
     33 namespace blink {
     34 
     35 enum AnimationMode {
     36     NoAnimation,
     37     FromToAnimation,
     38     FromByAnimation,
     39     ToAnimation,
     40     ByAnimation,
     41     ValuesAnimation,
     42     PathAnimation // Used by AnimateMotion.
     43 };
     44 
     45 // If we have 'inherit' as animation value, we need to grab the value
     46 // during the animation since the value can be animated itself.
     47 enum AnimatedPropertyValueType {
     48     RegularPropertyValue,
     49     InheritValue
     50 };
     51 
     52 enum CalcMode {
     53     CalcModeDiscrete,
     54     CalcModeLinear,
     55     CalcModePaced,
     56     CalcModeSpline
     57 };
     58 
     59 class SVGAnimationElement : public SVGSMILElement {
     60     DEFINE_WRAPPERTYPEINFO();
     61 public:
     62     // SVGAnimationElement
     63     float getStartTime() const;
     64     float getCurrentTime() const;
     65     float getSimpleDuration() const;
     66 
     67     void beginElement();
     68     void beginElementAt(float offset);
     69     void endElement();
     70     void endElementAt(float offset);
     71 
     72     DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(begin, beginEvent);
     73     DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(end, endEvent);
     74     DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(repeat, repeatEvent);
     75 
     76     static bool isTargetAttributeCSSProperty(SVGElement*, const QualifiedName&);
     77 
     78     virtual bool isAdditive();
     79     bool isAccumulated() const;
     80     AnimationMode animationMode() const { return m_animationMode; }
     81     CalcMode calcMode() const { return m_calcMode; }
     82 
     83     enum ShouldApplyAnimation {
     84         DontApplyAnimation,
     85         ApplyCSSAnimation,
     86         ApplyXMLAnimation
     87     };
     88 
     89     ShouldApplyAnimation shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName);
     90 
     91     AnimatedPropertyValueType fromPropertyValueType() const { return m_fromPropertyValueType; }
     92     AnimatedPropertyValueType toPropertyValueType() const { return m_toPropertyValueType; }
     93 
     94     template<typename AnimatedType, typename ParseTypeFromStringType>
     95     void adjustForInheritance(ParseTypeFromStringType parseTypeFromString, AnimatedPropertyValueType valueType, AnimatedType& animatedType, SVGElement* contextElement)
     96     {
     97         if (valueType != InheritValue)
     98             return;
     99         // Replace 'inherit' by its computed property value.
    100         String typeString;
    101         adjustForInheritance(contextElement, attributeName(), typeString);
    102         animatedType = parseTypeFromString(this, typeString);
    103     }
    104 
    105     template<typename AnimatedType>
    106     void animateDiscreteType(float percentage, const AnimatedType& fromType, const AnimatedType& toType, AnimatedType& animatedType)
    107     {
    108         if ((animationMode() == FromToAnimation && percentage > 0.5) || animationMode() == ToAnimation || percentage == 1) {
    109             animatedType = AnimatedType(toType);
    110             return;
    111         }
    112         animatedType = AnimatedType(fromType);
    113     }
    114 
    115     void animateAdditiveNumber(float percentage, unsigned repeatCount, float fromNumber, float toNumber, float toAtEndOfDurationNumber, float& animatedNumber)
    116     {
    117         float number;
    118         if (calcMode() == CalcModeDiscrete)
    119             number = percentage < 0.5 ? fromNumber : toNumber;
    120         else
    121             number = (toNumber - fromNumber) * percentage + fromNumber;
    122 
    123         if (isAccumulated() && repeatCount)
    124             number += toAtEndOfDurationNumber * repeatCount;
    125 
    126         if (isAdditive() && animationMode() != ToAnimation)
    127             animatedNumber += number;
    128         else
    129             animatedNumber = number;
    130     }
    131 
    132 protected:
    133     SVGAnimationElement(const QualifiedName&, Document&);
    134 
    135     void computeCSSPropertyValue(SVGElement*, CSSPropertyID, String& value);
    136     void determinePropertyValueTypes(const String& from, const String& to);
    137 
    138     bool isSupportedAttribute(const QualifiedName&);
    139     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
    140     virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
    141 
    142     enum AttributeType {
    143         AttributeTypeCSS,
    144         AttributeTypeXML,
    145         AttributeTypeAuto
    146     };
    147     AttributeType attributeType() const { return m_attributeType; }
    148 
    149     String toValue() const;
    150     String byValue() const;
    151     String fromValue() const;
    152 
    153     // from SVGSMILElement
    154     virtual void startedActiveInterval() OVERRIDE;
    155     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) OVERRIDE;
    156 
    157     AnimatedPropertyValueType m_fromPropertyValueType;
    158     AnimatedPropertyValueType m_toPropertyValueType;
    159 
    160     virtual void setTargetElement(SVGElement*) OVERRIDE;
    161     virtual void setAttributeName(const QualifiedName&) OVERRIDE;
    162 
    163     bool hasInvalidCSSAttributeType() const { return m_hasInvalidCSSAttributeType; }
    164 
    165     virtual void updateAnimationMode();
    166     void setAnimationMode(AnimationMode animationMode) { m_animationMode = animationMode; }
    167     void setCalcMode(CalcMode calcMode) { m_calcMode = calcMode; }
    168 
    169 private:
    170     virtual bool isValid() const OVERRIDE FINAL { return SVGTests::isValid(); }
    171 
    172     virtual void animationAttributeChanged() OVERRIDE;
    173     void setAttributeType(const AtomicString&);
    174 
    175     void checkInvalidCSSAttributeType(SVGElement*);
    176 
    177     virtual bool calculateToAtEndOfDurationValue(const String& toAtEndOfDurationString) = 0;
    178     virtual bool calculateFromAndToValues(const String& fromString, const String& toString) = 0;
    179     virtual bool calculateFromAndByValues(const String& fromString, const String& byString) = 0;
    180     virtual void calculateAnimatedValue(float percent, unsigned repeatCount, SVGSMILElement* resultElement) = 0;
    181     virtual float calculateDistance(const String& /*fromString*/, const String& /*toString*/) { return -1.f; }
    182 
    183     void currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to);
    184     void calculateKeyTimesForCalcModePaced();
    185     float calculatePercentFromKeyPoints(float percent) const;
    186     void currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const;
    187     float calculatePercentForSpline(float percent, unsigned splineIndex) const;
    188     float calculatePercentForFromTo(float percent) const;
    189     unsigned calculateKeyTimesIndex(float percent) const;
    190 
    191     void adjustForInheritance(SVGElement* targetElement, const QualifiedName& attributeName, String&);
    192 
    193     void setCalcMode(const AtomicString&);
    194 
    195     bool m_animationValid;
    196 
    197     AttributeType m_attributeType;
    198     Vector<String> m_values;
    199     // FIXME: We should probably use doubles for this, but there's no point
    200     // making such a change unless all SVG logic for sampling animations is
    201     // changed to use doubles.
    202     Vector<float> m_keyTimes;
    203     Vector<float> m_keyPoints;
    204     Vector<UnitBezier> m_keySplines;
    205     String m_lastValuesAnimationFrom;
    206     String m_lastValuesAnimationTo;
    207     bool m_hasInvalidCSSAttributeType;
    208     CalcMode m_calcMode;
    209     AnimationMode m_animationMode;
    210 };
    211 
    212 } // namespace blink
    213 
    214 #endif // SVGAnimationElement_h
    215