Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGAnimatedTypeAnimator.cpp
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 #include "config.h"
22 #include "core/svg/SVGAnimatedTypeAnimator.h"
23
24 #include "core/css/parser/CSSParser.h"
25 #include "core/svg/SVGAnimateTransformElement.h"
26 #include "core/svg/SVGAnimatedColor.h"
27 #include "core/svg/SVGAnimationElement.h"
28 #include "core/svg/SVGElement.h"
29 #include "core/svg/SVGLength.h"
30 #include "core/svg/SVGLengthList.h"
31 #include "core/svg/SVGNumber.h"
32 #include "core/svg/SVGPointList.h"
33 #include "core/svg/SVGString.h"
34 #include "core/svg/SVGTransformList.h"
35
36 namespace blink {
37
38 SVGAnimatedTypeAnimator::SVGAnimatedTypeAnimator(SVGAnimationElement* animationElement, SVGElement* contextElement)
39     : m_animationElement(animationElement)
40     , m_contextElement(contextElement)
41 {
42     ASSERT(m_animationElement);
43     ASSERT(m_contextElement);
44
45     const QualifiedName& attributeName = m_animationElement->attributeName();
46     m_animatedProperty = m_contextElement->propertyFromAttribute(attributeName);
47     m_type = m_animatedProperty ? m_animatedProperty->type()
48         : SVGElement::animatedPropertyTypeForCSSAttribute(attributeName);
49
50     // Only <animateTransform> is allowed to animate AnimatedTransformList.
51     // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties
52     if (m_type == AnimatedTransformList && !isSVGAnimateTransformElement(*animationElement))
53         m_type = AnimatedUnknown;
54
55     ASSERT(m_type != AnimatedPoint
56         && m_type != AnimatedStringList
57         && m_type != AnimatedTransform);
58 }
59
60 SVGAnimatedTypeAnimator::~SVGAnimatedTypeAnimator()
61 {
62 }
63
64 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::createPropertyForAnimation(const String& value)
65 {
66     if (isAnimatingSVGDom()) {
67         // SVG DOM animVal animation code-path.
68
69         if (m_type == AnimatedTransformList) {
70             // TransformList must be animated via <animateTransform>,
71             // and its {from,by,to} attribute values needs to be parsed w.r.t. its "type" attribute.
72             // Spec: http://www.w3.org/TR/SVG/single-page.html#animate-AnimateTransformElement
73             ASSERT(m_animationElement);
74             SVGTransformType transformType = toSVGAnimateTransformElement(m_animationElement)->transformType();
75             return SVGTransformList::create(transformType, value);
76         }
77
78         ASSERT(m_animatedProperty);
79         return m_animatedProperty->currentValueBase()->cloneForAnimation(value);
80     }
81
82     ASSERT(isAnimatingCSSProperty());
83
84     // CSS properties animation code-path.
85     // Create a basic instance of the corresponding SVG property.
86     // The instance will not have full context info. (e.g. SVGLengthMode)
87
88     switch (m_type) {
89     case AnimatedColor:
90         return SVGColorProperty::create(value.isEmpty() ? StyleColor::currentColor() : CSSParser::colorFromRGBColorString(value));
91     case AnimatedNumber: {
92         RefPtr<SVGNumber> property = SVGNumber::create();
93         property->setValueAsString(value, IGNORE_EXCEPTION);
94         return property.release();
95     }
96     case AnimatedLength: {
97         RefPtr<SVGLength> property = SVGLength::create(LengthModeOther);
98         property->setValueAsString(value, IGNORE_EXCEPTION);
99         return property.release();
100     }
101     case AnimatedLengthList: {
102         RefPtr<SVGLengthList> property = SVGLengthList::create(LengthModeOther);
103         property->setValueAsString(value, IGNORE_EXCEPTION);
104         return property.release();
105     }
106     case AnimatedString: {
107         RefPtr<SVGString> property = SVGString::create();
108         property->setValueAsString(value, IGNORE_EXCEPTION);
109         return property.release();
110     }
111
112     // These types don't appear in the table in SVGElement::animatedPropertyTypeForCSSAttribute() and thus don't need support.
113     case AnimatedAngle:
114     case AnimatedBoolean:
115     case AnimatedEnumeration:
116     case AnimatedInteger:
117     case AnimatedIntegerOptionalInteger:
118     case AnimatedNumberList:
119     case AnimatedNumberOptionalNumber:
120     case AnimatedPath:
121     case AnimatedPoint:
122     case AnimatedPoints:
123     case AnimatedPreserveAspectRatio:
124     case AnimatedRect:
125     case AnimatedStringList:
126     case AnimatedTransform:
127     case AnimatedTransformList:
128         ASSERT_NOT_REACHED();
129
130     case AnimatedUnknown:
131         ASSERT_NOT_REACHED();
132     };
133
134     ASSERT_NOT_REACHED();
135     return nullptr;
136 }
137
138 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::constructFromString(const String& value)
139 {
140     return createPropertyForAnimation(value);
141 }
142
143 void SVGAnimatedTypeAnimator::calculateFromAndToValues(RefPtr<SVGPropertyBase>& from, RefPtr<SVGPropertyBase>& to, const String& fromString, const String& toString)
144 {
145     from = constructFromString(fromString);
146     to = constructFromString(toString);
147 }
148
149 void SVGAnimatedTypeAnimator::calculateFromAndByValues(RefPtr<SVGPropertyBase>& from, RefPtr<SVGPropertyBase>& to, const String& fromString, const String& byString)
150 {
151     from = constructFromString(fromString);
152     to = constructFromString(byString);
153     // FIXME(oilpan): Below .get() should be removed after transition types are gone.
154     to->add(from.get(), m_contextElement);
155 }
156
157 namespace {
158
159 void setAnimatedValueOnAllTargetProperties(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list, const QualifiedName& attributeName, PassRefPtr<SVGPropertyBase> passValue)
160 {
161     RefPtr<SVGPropertyBase> value = passValue;
162
163     WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator it = list.begin();
164     WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator itEnd = list.end();
165     for (; it != itEnd; ++it) {
166         RefPtr<SVGAnimatedPropertyBase> animatedProperty = (*it)->propertyFromAttribute(attributeName);
167         if (animatedProperty)
168             animatedProperty->setAnimatedValue(value);
169     }
170 }
171
172 }
173
174 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::resetAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
175 {
176     ASSERT(isAnimatingSVGDom());
177     RefPtr<SVGPropertyBase> animatedValue = m_animatedProperty->createAnimatedValue();
178     ASSERT(animatedValue->type() == m_type);
179     setAnimatedValueOnAllTargetProperties(list, m_animatedProperty->attributeName(), animatedValue);
180
181     return animatedValue.release();
182 }
183
184 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::startAnimValAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
185 {
186     ASSERT(isAnimatingSVGDom());
187     SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
188
189     return resetAnimation(list);
190 }
191
192 void SVGAnimatedTypeAnimator::stopAnimValAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
193 {
194     ASSERT(isAnimatingSVGDom());
195     SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
196
197     WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator it = list.begin();
198     WillBeHeapVector<RawPtrWillBeMember<SVGElement> >::const_iterator itEnd = list.end();
199     for (; it != itEnd; ++it) {
200         RefPtr<SVGAnimatedPropertyBase> animatedProperty = (*it)->propertyFromAttribute(m_animatedProperty->attributeName());
201         if (animatedProperty)
202             animatedProperty->animationEnded();
203     }
204 }
205
206 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::resetAnimValToBaseVal(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
207 {
208     SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
209
210     return resetAnimation(list);
211 }
212
213 class ParsePropertyFromString {
214 public:
215     explicit ParsePropertyFromString(SVGAnimatedTypeAnimator* animator)
216         : m_animator(animator)
217     {
218     }
219
220     PassRefPtr<SVGPropertyBase> operator()(SVGAnimationElement*, const String& value)
221     {
222         return m_animator->createPropertyForAnimation(value);
223     }
224
225 private:
226     SVGAnimatedTypeAnimator* m_animator;
227 };
228
229 void SVGAnimatedTypeAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGPropertyBase* from, SVGPropertyBase* to, SVGPropertyBase* toAtEndOfDuration, SVGPropertyBase* animated)
230 {
231     ASSERT(m_animationElement);
232     ASSERT(m_contextElement);
233
234     RefPtr<SVGPropertyBase> fromValue = m_animationElement->animationMode() == ToAnimation ? animated : from;
235     RefPtr<SVGPropertyBase> toValue = to;
236     RefPtr<SVGPropertyBase> toAtEndOfDurationValue = toAtEndOfDuration;
237     RefPtr<SVGPropertyBase> animatedValue = animated;
238
239     // Apply CSS inheritance rules.
240     ParsePropertyFromString parsePropertyFromString(this);
241     m_animationElement->adjustForInheritance<RefPtr<SVGPropertyBase>, ParsePropertyFromString>(parsePropertyFromString, m_animationElement->fromPropertyValueType(), fromValue, m_contextElement);
242     m_animationElement->adjustForInheritance<RefPtr<SVGPropertyBase>, ParsePropertyFromString>(parsePropertyFromString, m_animationElement->toPropertyValueType(), toValue, m_contextElement);
243
244     animatedValue->calculateAnimatedValue(m_animationElement, percentage, repeatCount, fromValue, toValue, toAtEndOfDurationValue, m_contextElement);
245 }
246
247 float SVGAnimatedTypeAnimator::calculateDistance(const String& fromString, const String& toString)
248 {
249     ASSERT(m_animationElement);
250     ASSERT(m_contextElement);
251     RefPtr<SVGPropertyBase> fromValue = createPropertyForAnimation(fromString);
252     RefPtr<SVGPropertyBase> toValue = createPropertyForAnimation(toString);
253     return fromValue->calculateDistance(toValue, m_contextElement);
254 }
255
256 void SVGAnimatedTypeAnimator::trace(Visitor* visitor)
257 {
258     visitor->trace(m_animationElement);
259     visitor->trace(m_contextElement);
260 }
261
262 }