Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGAnimatedNewPropertyAnimator.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "core/svg/SVGAnimatedNewPropertyAnimator.h"
33
34 #include "core/svg/SVGAnimatedColor.h"
35 #include "core/svg/SVGAnimationElement.h"
36 #include "core/svg/SVGElementInstance.h"
37 #include "core/svg/SVGLength.h"
38 #include "core/svg/SVGLengthList.h"
39 #include "core/svg/SVGNumber.h"
40 #include "core/svg/SVGPointList.h"
41 #include "core/svg/SVGString.h"
42
43 namespace WebCore {
44
45 SVGAnimatedNewPropertyAnimator::SVGAnimatedNewPropertyAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement)
46     : SVGAnimatedTypeAnimator(type, animationElement, contextElement)
47 {
48     ASSERT(m_animationElement);
49     ASSERT(m_contextElement);
50
51     const QualifiedName& attributeName = m_animationElement->attributeName();
52     m_animatedProperty = m_contextElement->propertyFromAttribute(attributeName);
53     if (m_animatedProperty)
54         ASSERT(m_animatedProperty->type() == m_type);
55 }
56
57 SVGAnimatedNewPropertyAnimator::~SVGAnimatedNewPropertyAnimator()
58 {
59 }
60
61 PassRefPtr<NewSVGPropertyBase> SVGAnimatedNewPropertyAnimator::createPropertyForAnimation(const String& value)
62 {
63     if (isAnimatingSVGDom()) {
64         ASSERT(m_animatedProperty);
65
66         // SVG DOM animVal animation code-path.
67         return m_animatedProperty->currentValueBase()->cloneForAnimation(value);
68     }
69
70     ASSERT(isAnimatingCSSProperty());
71
72     // CSS properties animation code-path.
73     // Create a basic instance of the corresponding SVG property.
74     // The instance will not have full context info. (e.g. SVGLengthMode)
75
76     switch (m_type) {
77     case AnimatedColor:
78         return SVGColorProperty::create(value.isEmpty() ? StyleColor::currentColor() : SVGColor::colorFromRGBColorString(value));
79     case AnimatedNumber: {
80         RefPtr<SVGNumber> property = SVGNumber::create();
81         property->setValueAsString(value, IGNORE_EXCEPTION);
82         return property.release();
83     }
84     case AnimatedLength: {
85         RefPtr<SVGLength> property = SVGLength::create(LengthModeOther);
86         property->setValueAsString(value, IGNORE_EXCEPTION);
87         return property.release();
88     }
89     case AnimatedLengthList: {
90         RefPtr<SVGLengthList> property = SVGLengthList::create(LengthModeOther);
91         property->setValueAsString(value, IGNORE_EXCEPTION);
92         return property.release();
93     }
94     case AnimatedString: {
95         RefPtr<SVGString> property = SVGString::create();
96         property->setValueAsString(value, IGNORE_EXCEPTION);
97         return property.release();
98     }
99
100     // These types don't appear in the table in SVGElement::cssPropertyToTypeMap() and thus don't need support.
101     case AnimatedBoolean:
102     case AnimatedNumberList:
103     case AnimatedNumberOptionalNumber:
104     case AnimatedPoint:
105     case AnimatedPoints:
106     case AnimatedRect:
107         ASSERT_NOT_REACHED();
108
109     // These properties are not yet migrated to NewProperty implementation. see http://crbug.com/308818
110     case AnimatedAngle:
111     case AnimatedEnumeration:
112     case AnimatedInteger:
113     case AnimatedIntegerOptionalInteger:
114     case AnimatedPath:
115     case AnimatedPreserveAspectRatio:
116     case AnimatedStringList:
117     case AnimatedTransformList:
118         ASSERT_NOT_REACHED();
119
120     case AnimatedUnknown:
121         ASSERT_NOT_REACHED();
122     };
123
124     ASSERT_NOT_REACHED();
125     return 0;
126 }
127
128 PassOwnPtr<SVGAnimatedType> SVGAnimatedNewPropertyAnimator::constructFromString(const String& value)
129 {
130     return SVGAnimatedType::createNewProperty(createPropertyForAnimation(value));
131 }
132
133 namespace {
134
135 typedef void (NewSVGAnimatedPropertyBase::*NewSVGAnimatedPropertyMethod)();
136
137 void invokeMethodOnAllTargetProperties(const SVGElementAnimatedPropertyList& list, const QualifiedName& attributeName, NewSVGAnimatedPropertyMethod method)
138 {
139     SVGElementAnimatedPropertyList::const_iterator it = list.begin();
140     SVGElementAnimatedPropertyList::const_iterator itEnd = list.end();
141     for (; it != itEnd; ++it) {
142         RefPtr<NewSVGAnimatedPropertyBase> animatedProperty = it->element->propertyFromAttribute(attributeName);
143         if (animatedProperty)
144             (animatedProperty.get()->*method)();
145     }
146 }
147
148 void setAnimatedValueOnAllTargetProperties(const SVGElementAnimatedPropertyList& list, const QualifiedName& attributeName, PassRefPtr<NewSVGPropertyBase> passValue)
149 {
150     RefPtr<NewSVGPropertyBase> value = passValue;
151
152     SVGElementAnimatedPropertyList::const_iterator it = list.begin();
153     SVGElementAnimatedPropertyList::const_iterator itEnd = list.end();
154     for (; it != itEnd; ++it) {
155         RefPtr<NewSVGAnimatedPropertyBase> animatedProperty = it->element->propertyFromAttribute(attributeName);
156         if (animatedProperty)
157             animatedProperty->setAnimatedValue(value);
158     }
159 }
160
161 }
162
163 PassRefPtr<NewSVGPropertyBase> SVGAnimatedNewPropertyAnimator::resetAnimation(const SVGElementAnimatedPropertyList& list)
164 {
165     ASSERT(isAnimatingSVGDom());
166     RefPtr<NewSVGPropertyBase> animatedValue = m_animatedProperty->createAnimatedValue();
167     ASSERT(animatedValue->type() == m_type);
168     setAnimatedValueOnAllTargetProperties(list, m_animatedProperty->attributeName(), animatedValue);
169
170     return animatedValue.release();
171 }
172
173 PassOwnPtr<SVGAnimatedType> SVGAnimatedNewPropertyAnimator::startAnimValAnimation(const SVGElementAnimatedPropertyList& list)
174 {
175     ASSERT(isAnimatingSVGDom());
176     SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
177
178     invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animationStarted);
179
180     return SVGAnimatedType::createNewProperty(resetAnimation(list));
181 }
182
183 void SVGAnimatedNewPropertyAnimator::stopAnimValAnimation(const SVGElementAnimatedPropertyList& list)
184 {
185     ASSERT(isAnimatingSVGDom());
186     SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
187
188     invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animationEnded);
189 }
190
191 void SVGAnimatedNewPropertyAnimator::resetAnimValToBaseVal(const SVGElementAnimatedPropertyList& list, SVGAnimatedType* animated)
192 {
193     SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
194
195     animated->newProperty() = resetAnimation(list);
196 }
197
198 void SVGAnimatedNewPropertyAnimator::animValWillChange(const SVGElementAnimatedPropertyList& list)
199 {
200     ASSERT(isAnimatingSVGDom());
201     SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
202
203     invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animValWillChange);
204 }
205
206 void SVGAnimatedNewPropertyAnimator::animValDidChange(const SVGElementAnimatedPropertyList& list)
207 {
208     ASSERT(isAnimatingSVGDom());
209     SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
210
211     invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animValDidChange);
212 }
213
214 void SVGAnimatedNewPropertyAnimator::addAnimatedTypes(SVGAnimatedType* from, SVGAnimatedType* to)
215 {
216     to->newProperty()->add(from->newProperty(), m_contextElement);
217 }
218
219 class ParsePropertyFromString {
220 public:
221     explicit ParsePropertyFromString(SVGAnimatedNewPropertyAnimator* animator)
222         : m_animator(animator)
223     {
224     }
225
226     PassRefPtr<NewSVGPropertyBase> operator()(SVGAnimationElement*, const String& value)
227     {
228         return m_animator->createPropertyForAnimation(value);
229     }
230
231 private:
232     SVGAnimatedNewPropertyAnimator* m_animator;
233 };
234
235 void SVGAnimatedNewPropertyAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated)
236 {
237     ASSERT(m_animationElement);
238     ASSERT(m_contextElement);
239
240     RefPtr<NewSVGPropertyBase> fromValue = m_animationElement->animationMode() == ToAnimation ? animated->newProperty() : from->newProperty();
241     RefPtr<NewSVGPropertyBase> toValue = to->newProperty();
242     RefPtr<NewSVGPropertyBase> toAtEndOfDurationValue = toAtEndOfDuration->newProperty();
243     RefPtr<NewSVGPropertyBase> animatedValue = animated->newProperty();
244
245     // Apply CSS inheritance rules.
246     ParsePropertyFromString parsePropertyFromString(this);
247     m_animationElement->adjustForInheritance<RefPtr<NewSVGPropertyBase>, ParsePropertyFromString>(parsePropertyFromString, m_animationElement->fromPropertyValueType(), fromValue, m_contextElement);
248     m_animationElement->adjustForInheritance<RefPtr<NewSVGPropertyBase>, ParsePropertyFromString>(parsePropertyFromString, m_animationElement->toPropertyValueType(), toValue, m_contextElement);
249
250     animatedValue->calculateAnimatedValue(m_animationElement, percentage, repeatCount, fromValue, toValue, toAtEndOfDurationValue, m_contextElement);
251 }
252
253 float SVGAnimatedNewPropertyAnimator::calculateDistance(const String& fromString, const String& toString)
254 {
255     ASSERT(m_animationElement);
256     ASSERT(m_contextElement);
257     RefPtr<NewSVGPropertyBase> fromValue = createPropertyForAnimation(fromString);
258     RefPtr<NewSVGPropertyBase> toValue = createPropertyForAnimation(toString);
259     return fromValue->calculateDistance(toValue, m_contextElement);
260 }
261
262 } // namespace WebCore