2 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
3 * Copyright (C) 2013 Samsung Electronics. All rights reserved.
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.
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.
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.
22 #include "core/svg/SVGAnimatedTypeAnimator.h"
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"
38 SVGAnimatedTypeAnimator::SVGAnimatedTypeAnimator(SVGAnimationElement* animationElement, SVGElement* contextElement)
39 : m_animationElement(animationElement)
40 , m_contextElement(contextElement)
42 ASSERT(m_animationElement);
43 ASSERT(m_contextElement);
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);
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;
55 ASSERT(m_type != AnimatedPoint
56 && m_type != AnimatedStringList
57 && m_type != AnimatedTransform);
60 SVGAnimatedTypeAnimator::~SVGAnimatedTypeAnimator()
64 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::createPropertyForAnimation(const String& value)
66 if (isAnimatingSVGDom()) {
67 // SVG DOM animVal animation code-path.
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);
78 ASSERT(m_animatedProperty);
79 return m_animatedProperty->currentValueBase()->cloneForAnimation(value);
82 ASSERT(isAnimatingCSSProperty());
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)
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();
96 case AnimatedLength: {
97 RefPtr<SVGLength> property = SVGLength::create(LengthModeOther);
98 property->setValueAsString(value, IGNORE_EXCEPTION);
99 return property.release();
101 case AnimatedLengthList: {
102 RefPtr<SVGLengthList> property = SVGLengthList::create(LengthModeOther);
103 property->setValueAsString(value, IGNORE_EXCEPTION);
104 return property.release();
106 case AnimatedString: {
107 RefPtr<SVGString> property = SVGString::create();
108 property->setValueAsString(value, IGNORE_EXCEPTION);
109 return property.release();
112 // These types don't appear in the table in SVGElement::animatedPropertyTypeForCSSAttribute() and thus don't need support.
114 case AnimatedBoolean:
115 case AnimatedEnumeration:
116 case AnimatedInteger:
117 case AnimatedIntegerOptionalInteger:
118 case AnimatedNumberList:
119 case AnimatedNumberOptionalNumber:
123 case AnimatedPreserveAspectRatio:
125 case AnimatedStringList:
126 case AnimatedTransform:
127 case AnimatedTransformList:
128 ASSERT_NOT_REACHED();
130 case AnimatedUnknown:
131 ASSERT_NOT_REACHED();
134 ASSERT_NOT_REACHED();
138 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::constructFromString(const String& value)
140 return createPropertyForAnimation(value);
143 void SVGAnimatedTypeAnimator::calculateFromAndToValues(RefPtr<SVGPropertyBase>& from, RefPtr<SVGPropertyBase>& to, const String& fromString, const String& toString)
145 from = constructFromString(fromString);
146 to = constructFromString(toString);
149 void SVGAnimatedTypeAnimator::calculateFromAndByValues(RefPtr<SVGPropertyBase>& from, RefPtr<SVGPropertyBase>& to, const String& fromString, const String& byString)
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);
159 void setAnimatedValueOnAllTargetProperties(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list, const QualifiedName& attributeName, PassRefPtr<SVGPropertyBase> passValue)
161 RefPtr<SVGPropertyBase> value = passValue;
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);
174 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::resetAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
176 ASSERT(isAnimatingSVGDom());
177 RefPtr<SVGPropertyBase> animatedValue = m_animatedProperty->createAnimatedValue();
178 ASSERT(animatedValue->type() == m_type);
179 setAnimatedValueOnAllTargetProperties(list, m_animatedProperty->attributeName(), animatedValue);
181 return animatedValue.release();
184 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::startAnimValAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
186 ASSERT(isAnimatingSVGDom());
187 SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
189 return resetAnimation(list);
192 void SVGAnimatedTypeAnimator::stopAnimValAnimation(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
194 ASSERT(isAnimatingSVGDom());
195 SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
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();
206 PassRefPtr<SVGPropertyBase> SVGAnimatedTypeAnimator::resetAnimValToBaseVal(const WillBeHeapVector<RawPtrWillBeMember<SVGElement> >& list)
208 SVGElement::InstanceUpdateBlocker blocker(m_contextElement);
210 return resetAnimation(list);
213 class ParsePropertyFromString {
215 explicit ParsePropertyFromString(SVGAnimatedTypeAnimator* animator)
216 : m_animator(animator)
220 PassRefPtr<SVGPropertyBase> operator()(SVGAnimationElement*, const String& value)
222 return m_animator->createPropertyForAnimation(value);
226 SVGAnimatedTypeAnimator* m_animator;
229 void SVGAnimatedTypeAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGPropertyBase* from, SVGPropertyBase* to, SVGPropertyBase* toAtEndOfDuration, SVGPropertyBase* animated)
231 ASSERT(m_animationElement);
232 ASSERT(m_contextElement);
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;
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);
244 animatedValue->calculateAnimatedValue(m_animationElement, percentage, repeatCount, fromValue, toValue, toAtEndOfDurationValue, m_contextElement);
247 float SVGAnimatedTypeAnimator::calculateDistance(const String& fromString, const String& toString)
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);
256 void SVGAnimatedTypeAnimator::trace(Visitor* visitor)
258 visitor->trace(m_animationElement);
259 visitor->trace(m_contextElement);