2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "core/svg/SVGAnimatedNewPropertyAnimator.h"
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"
45 SVGAnimatedNewPropertyAnimator::SVGAnimatedNewPropertyAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement)
46 : SVGAnimatedTypeAnimator(type, animationElement, contextElement)
48 ASSERT(m_animationElement);
49 ASSERT(m_contextElement);
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);
57 SVGAnimatedNewPropertyAnimator::~SVGAnimatedNewPropertyAnimator()
61 PassRefPtr<NewSVGPropertyBase> SVGAnimatedNewPropertyAnimator::createPropertyForAnimation(const String& value)
63 if (isAnimatingSVGDom()) {
64 ASSERT(m_animatedProperty);
66 // SVG DOM animVal animation code-path.
67 return m_animatedProperty->currentValueBase()->cloneForAnimation(value);
70 ASSERT(isAnimatingCSSProperty());
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)
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();
84 case AnimatedLength: {
85 RefPtr<SVGLength> property = SVGLength::create(LengthModeOther);
86 property->setValueAsString(value, IGNORE_EXCEPTION);
87 return property.release();
89 case AnimatedLengthList: {
90 RefPtr<SVGLengthList> property = SVGLengthList::create(LengthModeOther);
91 property->setValueAsString(value, IGNORE_EXCEPTION);
92 return property.release();
94 case AnimatedString: {
95 RefPtr<SVGString> property = SVGString::create();
96 property->setValueAsString(value, IGNORE_EXCEPTION);
97 return property.release();
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:
107 ASSERT_NOT_REACHED();
109 // These properties are not yet migrated to NewProperty implementation. see http://crbug.com/308818
111 case AnimatedEnumeration:
112 case AnimatedInteger:
113 case AnimatedIntegerOptionalInteger:
115 case AnimatedPreserveAspectRatio:
116 case AnimatedStringList:
117 case AnimatedTransformList:
118 ASSERT_NOT_REACHED();
120 case AnimatedUnknown:
121 ASSERT_NOT_REACHED();
124 ASSERT_NOT_REACHED();
128 PassOwnPtr<SVGAnimatedType> SVGAnimatedNewPropertyAnimator::constructFromString(const String& value)
130 return SVGAnimatedType::createNewProperty(createPropertyForAnimation(value));
135 typedef void (NewSVGAnimatedPropertyBase::*NewSVGAnimatedPropertyMethod)();
137 void invokeMethodOnAllTargetProperties(const SVGElementAnimatedPropertyList& list, const QualifiedName& attributeName, NewSVGAnimatedPropertyMethod method)
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)();
148 void setAnimatedValueOnAllTargetProperties(const SVGElementAnimatedPropertyList& list, const QualifiedName& attributeName, PassRefPtr<NewSVGPropertyBase> passValue)
150 RefPtr<NewSVGPropertyBase> value = passValue;
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);
163 PassRefPtr<NewSVGPropertyBase> SVGAnimatedNewPropertyAnimator::resetAnimation(const SVGElementAnimatedPropertyList& list)
165 ASSERT(isAnimatingSVGDom());
166 RefPtr<NewSVGPropertyBase> animatedValue = m_animatedProperty->createAnimatedValue();
167 ASSERT(animatedValue->type() == m_type);
168 setAnimatedValueOnAllTargetProperties(list, m_animatedProperty->attributeName(), animatedValue);
170 return animatedValue.release();
173 PassOwnPtr<SVGAnimatedType> SVGAnimatedNewPropertyAnimator::startAnimValAnimation(const SVGElementAnimatedPropertyList& list)
175 ASSERT(isAnimatingSVGDom());
176 SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
178 invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animationStarted);
180 return SVGAnimatedType::createNewProperty(resetAnimation(list));
183 void SVGAnimatedNewPropertyAnimator::stopAnimValAnimation(const SVGElementAnimatedPropertyList& list)
185 ASSERT(isAnimatingSVGDom());
186 SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
188 invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animationEnded);
191 void SVGAnimatedNewPropertyAnimator::resetAnimValToBaseVal(const SVGElementAnimatedPropertyList& list, SVGAnimatedType* animated)
193 SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
195 animated->newProperty() = resetAnimation(list);
198 void SVGAnimatedNewPropertyAnimator::animValWillChange(const SVGElementAnimatedPropertyList& list)
200 ASSERT(isAnimatingSVGDom());
201 SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
203 invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animValWillChange);
206 void SVGAnimatedNewPropertyAnimator::animValDidChange(const SVGElementAnimatedPropertyList& list)
208 ASSERT(isAnimatingSVGDom());
209 SVGElementInstance::InstanceUpdateBlocker blocker(m_contextElement);
211 invokeMethodOnAllTargetProperties(list, m_animatedProperty->attributeName(), &NewSVGAnimatedPropertyBase::animValDidChange);
214 void SVGAnimatedNewPropertyAnimator::addAnimatedTypes(SVGAnimatedType* from, SVGAnimatedType* to)
216 to->newProperty()->add(from->newProperty(), m_contextElement);
219 class ParsePropertyFromString {
221 explicit ParsePropertyFromString(SVGAnimatedNewPropertyAnimator* animator)
222 : m_animator(animator)
226 PassRefPtr<NewSVGPropertyBase> operator()(SVGAnimationElement*, const String& value)
228 return m_animator->createPropertyForAnimation(value);
232 SVGAnimatedNewPropertyAnimator* m_animator;
235 void SVGAnimatedNewPropertyAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated)
237 ASSERT(m_animationElement);
238 ASSERT(m_contextElement);
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();
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);
250 animatedValue->calculateAnimatedValue(m_animationElement, percentage, repeatCount, fromValue, toValue, toAtEndOfDurationValue, m_contextElement);
253 float SVGAnimatedNewPropertyAnimator::calculateDistance(const String& fromString, const String& toString)
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);
262 } // namespace WebCore