Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
      3  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #ifndef SVGAnimatedTypeAnimator_h
     22 #define SVGAnimatedTypeAnimator_h
     23 
     24 #include "core/svg/SVGAnimatedType.h"
     25 #include "core/svg/SVGElementInstance.h"
     26 #include "core/svg/properties/SVGAnimatedProperty.h"
     27 #include "wtf/PassOwnPtr.h"
     28 
     29 namespace WebCore {
     30 
     31 struct SVGElementAnimatedProperties {
     32     SVGElementAnimatedProperties();
     33 
     34     SVGElementAnimatedProperties(SVGElement*, Vector<RefPtr<SVGAnimatedProperty> >&);
     35 
     36     SVGElement* element;
     37     Vector<RefPtr<SVGAnimatedProperty> > properties;
     38 };
     39 typedef Vector<SVGElementAnimatedProperties> SVGElementAnimatedPropertyList;
     40 
     41 class SVGAnimationElement;
     42 
     43 class SVGAnimatedTypeAnimator {
     44     WTF_MAKE_FAST_ALLOCATED;
     45 public:
     46     virtual ~SVGAnimatedTypeAnimator();
     47     virtual PassOwnPtr<SVGAnimatedType> constructFromString(const String&) = 0;
     48 
     49     virtual PassOwnPtr<SVGAnimatedType> startAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0;
     50     virtual void stopAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0;
     51     virtual void resetAnimValToBaseVal(const SVGElementAnimatedPropertyList&, SVGAnimatedType*) = 0;
     52     virtual void animValWillChange(const SVGElementAnimatedPropertyList&) = 0;
     53     virtual void animValDidChange(const SVGElementAnimatedPropertyList&) = 0;
     54     virtual void addAnimatedTypes(SVGAnimatedType*, SVGAnimatedType*) = 0;
     55 
     56     virtual void calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*) = 0;
     57     virtual float calculateDistance(const String& fromString, const String& toString) = 0;
     58 
     59     void calculateFromAndToValues(OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, const String& fromString, const String& toString);
     60     void calculateFromAndByValues(OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, const String& fromString, const String& byString);
     61 
     62     void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; }
     63     AnimatedPropertyType type() const { return m_type; }
     64 
     65     SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement*, const QualifiedName&);
     66 
     67 protected:
     68     SVGAnimatedTypeAnimator(AnimatedPropertyType, SVGAnimationElement*, SVGElement*);
     69 
     70     // Helpers for animators that operate on single types, eg. just one SVGAnimatedInteger.
     71     template<typename AnimValType>
     72     typename AnimValType::ContentType* constructFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes)
     73     {
     74         ASSERT(animatedTypes[0].properties.size() == 1);
     75         const typename AnimValType::ContentType& animatedType = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue();
     76 
     77         typename AnimValType::ContentType* copy = new typename AnimValType::ContentType(animatedType);
     78         executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, copy);
     79         return copy;
     80     }
     81 
     82     template<typename AnimValType>
     83     void resetFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, typename AnimValType::ContentType& (SVGAnimatedType::*getter)())
     84     {
     85         ASSERT(animatedTypes[0].properties.size() == 1);
     86         ASSERT(type);
     87         ASSERT(type->type() == m_type);
     88         typename AnimValType::ContentType& animatedTypeValue = (type->*getter)();
     89         animatedTypeValue = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue();
     90 
     91         executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue);
     92     }
     93 
     94     template<typename AnimValType>
     95     void stopAnimValAnimationForType(const SVGElementAnimatedPropertyList& animatedTypes)
     96     {
     97         ASSERT(animatedTypes[0].properties.size() == 1);
     98         executeAction<AnimValType>(StopAnimationAction, animatedTypes, 0);
     99     }
    100 
    101     template<typename AnimValType>
    102     void animValDidChangeForType(const SVGElementAnimatedPropertyList& animatedTypes)
    103     {
    104         ASSERT(animatedTypes[0].properties.size() == 1);
    105         executeAction<AnimValType>(AnimValDidChangeAction, animatedTypes, 0);
    106     }
    107 
    108     template<typename AnimValType>
    109     void animValWillChangeForType(const SVGElementAnimatedPropertyList& animatedTypes)
    110     {
    111         ASSERT(animatedTypes[0].properties.size() == 1);
    112         executeAction<AnimValType>(AnimValWillChangeAction, animatedTypes, 0);
    113     }
    114 
    115     // Helpers for animators that operate on pair types, eg. a pair of SVGAnimatedIntegers.
    116     template<typename AnimValType1, typename AnimValType2>
    117     pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>* constructFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes)
    118     {
    119         ASSERT(animatedTypes[0].properties.size() == 2);
    120         const typename AnimValType1::ContentType& firstType = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue();
    121         const typename AnimValType2::ContentType& secondType = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue();
    122 
    123         pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>* copy = new pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>(firstType, secondType);
    124         executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, &copy->first);
    125         executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, &copy->second);
    126         return copy;
    127     }
    128 
    129     template<typename AnimValType1, typename AnimValType2>
    130     void resetFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& (SVGAnimatedType::*getter)())
    131     {
    132         ASSERT(animatedTypes[0].properties.size() == 2);
    133         ASSERT(type);
    134         ASSERT(type->type() == m_type);
    135 
    136         pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& animatedTypeValue = (type->*getter)();
    137         animatedTypeValue.first = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue();
    138         animatedTypeValue.second = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue();
    139 
    140         executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue.first);
    141         executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, &animatedTypeValue.second);
    142     }
    143 
    144     template<typename AnimValType1, typename AnimValType2>
    145     void stopAnimValAnimationForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
    146     {
    147         ASSERT(animatedTypes[0].properties.size() == 2);
    148         executeAction<AnimValType1>(StopAnimationAction, animatedTypes, 0);
    149         executeAction<AnimValType2>(StopAnimationAction, animatedTypes, 1);
    150     }
    151 
    152     template<typename AnimValType1, typename AnimValType2>
    153     void animValDidChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
    154     {
    155         ASSERT(animatedTypes[0].properties.size() == 2);
    156         executeAction<AnimValType1>(AnimValDidChangeAction, animatedTypes, 0);
    157         executeAction<AnimValType2>(AnimValDidChangeAction, animatedTypes, 1);
    158     }
    159 
    160     template<typename AnimValType1, typename AnimValType2>
    161     void animValWillChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
    162     {
    163         ASSERT(animatedTypes[0].properties.size() == 2);
    164         executeAction<AnimValType1>(AnimValWillChangeAction, animatedTypes, 0);
    165         executeAction<AnimValType2>(AnimValWillChangeAction, animatedTypes, 1);
    166     }
    167 
    168     template<typename AnimValType>
    169     AnimValType* castAnimatedPropertyToActualType(SVGAnimatedProperty* property)
    170     {
    171         ASSERT(property);
    172         ASSERT(property->contextElement());
    173         // We can't assert property->animatedPropertyType() == m_type, as there's an exception for SVGMarkerElements orient attribute.
    174         if (property->animatedPropertyType() != m_type) {
    175             ASSERT(m_type == AnimatedAngle);
    176             ASSERT(property->animatedPropertyType() == AnimatedEnumeration);
    177         }
    178         return static_cast<AnimValType*>(property);
    179     }
    180 
    181     AnimatedPropertyType m_type;
    182     SVGAnimationElement* m_animationElement;
    183     SVGElement* m_contextElement;
    184 
    185 private:
    186     enum AnimationAction {
    187         StartAnimationAction,
    188         StopAnimationAction,
    189         AnimValWillChangeAction,
    190         AnimValDidChangeAction
    191     };
    192 
    193     template<typename AnimValType>
    194     void executeAction(AnimationAction action, const SVGElementAnimatedPropertyList& animatedTypes, unsigned whichProperty, typename AnimValType::ContentType* type = 0)
    195     {
    196         SVGElementInstance::InstanceUpdateBlocker blocker(animatedTypes[0].element);
    197 
    198         SVGElementAnimatedPropertyList::const_iterator end = animatedTypes.end();
    199         for (SVGElementAnimatedPropertyList::const_iterator it = animatedTypes.begin(); it != end; ++it) {
    200             ASSERT_WITH_SECURITY_IMPLICATION(whichProperty < it->properties.size());
    201             AnimValType* property = castAnimatedPropertyToActualType<AnimValType>(it->properties[whichProperty].get());
    202 
    203             switch (action) {
    204             case StartAnimationAction:
    205                 ASSERT(type);
    206                 if (!property->isAnimating())
    207                     property->animationStarted(type);
    208                 break;
    209             case StopAnimationAction:
    210                 ASSERT(!type);
    211                 property->animationEnded();
    212                 break;
    213             case AnimValWillChangeAction:
    214                 ASSERT(!type);
    215                 property->animValWillChange();
    216                 break;
    217             case AnimValDidChangeAction:
    218                 ASSERT(!type);
    219                 property->animValDidChange();
    220                 break;
    221             }
    222         }
    223     }
    224 };
    225 
    226 } // namespace WebCore
    227 
    228 #endif // SVGAnimatedTypeAnimator_h
    229