OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2008 Apple Inc. All rights reserved. | 4 * Copyright (C) 2008 Apple Inc. All rights reserved. |
5 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 5 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
11 * | 11 * |
12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
21 */ | 21 */ |
22 | 22 |
23 #include "core/svg/SVGAnimateElement.h" | 23 #include "core/svg/SVGAnimateElement.h" |
24 | 24 |
25 #include "core/css/CSSComputedStyleDeclaration.h" | 25 #include "core/css/CSSComputedStyleDeclaration.h" |
26 #include "core/css/StylePropertySet.h" | 26 #include "core/css/StylePropertySet.h" |
27 #include "core/dom/Document.h" | 27 #include "core/dom/Document.h" |
28 #include "core/dom/QualifiedName.h" | 28 #include "core/dom/QualifiedName.h" |
29 #include "core/dom/StyleChangeReason.h" | 29 #include "core/dom/StyleChangeReason.h" |
| 30 #include "core/svg/SVGAnimatedColor.h" |
| 31 #include "core/svg/SVGLength.h" |
| 32 #include "core/svg/SVGLengthList.h" |
| 33 #include "core/svg/SVGNumber.h" |
| 34 #include "core/svg/SVGString.h" |
| 35 #include "core/svg/properties/SVGAnimatedProperty.h" |
30 #include "core/svg/properties/SVGProperty.h" | 36 #include "core/svg/properties/SVGProperty.h" |
31 | 37 |
32 namespace blink { | 38 namespace blink { |
33 | 39 |
34 namespace { | 40 namespace { |
35 | 41 |
36 bool isTargetAttributeCSSProperty(const SVGElement& targetElement, | 42 bool isTargetAttributeCSSProperty(const SVGElement& targetElement, |
37 const QualifiedName& attributeName) { | 43 const QualifiedName& attributeName) { |
38 return SVGElement::isAnimatableCSSProperty(attributeName) || | 44 return SVGElement::isAnimatableCSSProperty(attributeName) || |
39 targetElement.isPresentationAttribute(attributeName); | 45 targetElement.isPresentationAttribute(attributeName); |
(...skipping 21 matching lines...) Expand all Loading... |
61 !SVGElement::isAnimatableCSSProperty(attributeName)) | 67 !SVGElement::isAnimatableCSSProperty(attributeName)) |
62 return RegularPropertyValue; | 68 return RegularPropertyValue; |
63 return InheritValue; | 69 return InheritValue; |
64 } | 70 } |
65 | 71 |
66 } // unnamed namespace | 72 } // unnamed namespace |
67 | 73 |
68 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, | 74 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, |
69 Document& document) | 75 Document& document) |
70 : SVGAnimationElement(tagName, document), | 76 : SVGAnimationElement(tagName, document), |
71 m_animator(this), | 77 m_type(AnimatedUnknown), |
| 78 m_cssPropertyId(CSSPropertyInvalid), |
72 m_fromPropertyValueType(RegularPropertyValue), | 79 m_fromPropertyValueType(RegularPropertyValue), |
73 m_toPropertyValueType(RegularPropertyValue), | 80 m_toPropertyValueType(RegularPropertyValue), |
74 m_attributeType(AttributeTypeAuto), | 81 m_attributeType(AttributeTypeAuto), |
75 m_hasInvalidCSSAttributeType(false) {} | 82 m_hasInvalidCSSAttributeType(false) {} |
76 | 83 |
77 SVGAnimateElement* SVGAnimateElement::create(Document& document) { | 84 SVGAnimateElement* SVGAnimateElement::create(Document& document) { |
78 return new SVGAnimateElement(SVGNames::animateTag, document); | 85 return new SVGAnimateElement(SVGNames::animateTag, document); |
79 } | 86 } |
80 | 87 |
81 SVGAnimateElement::~SVGAnimateElement() {} | 88 SVGAnimateElement::~SVGAnimateElement() {} |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 } | 120 } |
114 | 121 |
115 void SVGAnimateElement::svgAttributeChanged(const QualifiedName& attrName) { | 122 void SVGAnimateElement::svgAttributeChanged(const QualifiedName& attrName) { |
116 if (attrName == SVGNames::attributeTypeAttr) { | 123 if (attrName == SVGNames::attributeTypeAttr) { |
117 animationAttributeChanged(); | 124 animationAttributeChanged(); |
118 return; | 125 return; |
119 } | 126 } |
120 SVGAnimationElement::svgAttributeChanged(attrName); | 127 SVGAnimationElement::svgAttributeChanged(attrName); |
121 } | 128 } |
122 | 129 |
| 130 void SVGAnimateElement::resolveTargetProperty() { |
| 131 DCHECK(targetElement()); |
| 132 m_targetProperty = targetElement()->propertyFromAttribute(attributeName()); |
| 133 if (m_targetProperty) { |
| 134 m_type = m_targetProperty->type(); |
| 135 m_cssPropertyId = m_targetProperty->cssPropertyId(); |
| 136 |
| 137 // Only <animateTransform> is allowed to animate AnimatedTransformList. |
| 138 // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties |
| 139 if (m_type == AnimatedTransformList) { |
| 140 m_type = AnimatedUnknown; |
| 141 m_cssPropertyId = CSSPropertyInvalid; |
| 142 } |
| 143 } else { |
| 144 m_type = SVGElement::animatedPropertyTypeForCSSAttribute(attributeName()); |
| 145 m_cssPropertyId = m_type != AnimatedUnknown |
| 146 ? cssPropertyID(attributeName().localName()) |
| 147 : CSSPropertyInvalid; |
| 148 } |
| 149 DCHECK(m_type != AnimatedPoint && m_type != AnimatedStringList && |
| 150 m_type != AnimatedTransform && m_type != AnimatedTransformList); |
| 151 } |
| 152 |
| 153 void SVGAnimateElement::clearTargetProperty() { |
| 154 m_targetProperty = nullptr; |
| 155 m_type = AnimatedUnknown; |
| 156 m_cssPropertyId = CSSPropertyInvalid; |
| 157 } |
| 158 |
123 AnimatedPropertyType SVGAnimateElement::animatedPropertyType() { | 159 AnimatedPropertyType SVGAnimateElement::animatedPropertyType() { |
124 if (!targetElement()) | 160 if (!targetElement()) |
125 return AnimatedUnknown; | 161 return AnimatedUnknown; |
126 | 162 resolveTargetProperty(); |
127 m_animator.reset(*targetElement()); | 163 return m_type; |
128 return m_animator.type(); | |
129 } | 164 } |
130 | 165 |
131 bool SVGAnimateElement::hasValidTarget() { | 166 bool SVGAnimateElement::hasValidTarget() { |
132 return SVGAnimationElement::hasValidTarget() && hasValidAttributeName() && | 167 return SVGAnimationElement::hasValidTarget() && hasValidAttributeName() && |
133 hasValidAttributeType(); | 168 hasValidAttributeType(); |
134 } | 169 } |
135 | 170 |
136 bool SVGAnimateElement::hasValidAttributeName() const { | 171 bool SVGAnimateElement::hasValidAttributeName() const { |
137 return attributeName() != anyQName(); | 172 return attributeName() != anyQName(); |
138 } | 173 } |
(...skipping 14 matching lines...) Expand all Loading... |
153 // Always animate CSS properties using the ApplyCSSAnimation code path, | 188 // Always animate CSS properties using the ApplyCSSAnimation code path, |
154 // regardless of the attributeType value. | 189 // regardless of the attributeType value. |
155 if (isTargetAttributeCSSProperty(targetElement, attributeName)) | 190 if (isTargetAttributeCSSProperty(targetElement, attributeName)) |
156 return true; | 191 return true; |
157 | 192 |
158 // If attributeType="CSS" and attributeName doesn't point to a CSS property, | 193 // If attributeType="CSS" and attributeName doesn't point to a CSS property, |
159 // ignore the animation. | 194 // ignore the animation. |
160 return getAttributeType() != AttributeTypeCSS; | 195 return getAttributeType() != AttributeTypeCSS; |
161 } | 196 } |
162 | 197 |
| 198 SVGPropertyBase* SVGAnimateElement::createPropertyForAttributeAnimation( |
| 199 const String& value) const { |
| 200 // SVG DOM animVal animation code-path. |
| 201 // TransformList must be animated via <animateTransform>, and its |
| 202 // {from,by,to} attribute values needs to be parsed w.r.t. its "type" |
| 203 // attribute. Spec: |
| 204 // http://www.w3.org/TR/SVG/single-page.html#animate-AnimateTransformElement |
| 205 DCHECK_NE(m_type, AnimatedTransformList); |
| 206 DCHECK(m_targetProperty); |
| 207 return m_targetProperty->currentValueBase()->cloneForAnimation(value); |
| 208 } |
| 209 |
| 210 SVGPropertyBase* SVGAnimateElement::createPropertyForCSSAnimation( |
| 211 const String& value) const { |
| 212 // CSS properties animation code-path. |
| 213 // Create a basic instance of the corresponding SVG property. |
| 214 // The instance will not have full context info. (e.g. SVGLengthMode) |
| 215 switch (m_type) { |
| 216 case AnimatedColor: |
| 217 return SVGColorProperty::create(value); |
| 218 case AnimatedNumber: { |
| 219 SVGNumber* property = SVGNumber::create(); |
| 220 property->setValueAsString(value); |
| 221 return property; |
| 222 } |
| 223 case AnimatedLength: { |
| 224 SVGLength* property = SVGLength::create(); |
| 225 property->setValueAsString(value); |
| 226 return property; |
| 227 } |
| 228 case AnimatedLengthList: { |
| 229 SVGLengthList* property = SVGLengthList::create(); |
| 230 property->setValueAsString(value); |
| 231 return property; |
| 232 } |
| 233 case AnimatedString: { |
| 234 SVGString* property = SVGString::create(); |
| 235 property->setValueAsString(value); |
| 236 return property; |
| 237 } |
| 238 // These types don't appear in the table in |
| 239 // SVGElement::animatedPropertyTypeForCSSAttribute() and thus don't need |
| 240 // support. |
| 241 case AnimatedAngle: |
| 242 case AnimatedBoolean: |
| 243 case AnimatedEnumeration: |
| 244 case AnimatedInteger: |
| 245 case AnimatedIntegerOptionalInteger: |
| 246 case AnimatedNumberList: |
| 247 case AnimatedNumberOptionalNumber: |
| 248 case AnimatedPath: |
| 249 case AnimatedPoint: |
| 250 case AnimatedPoints: |
| 251 case AnimatedPreserveAspectRatio: |
| 252 case AnimatedRect: |
| 253 case AnimatedStringList: |
| 254 case AnimatedTransform: |
| 255 case AnimatedTransformList: |
| 256 case AnimatedUnknown: |
| 257 break; |
| 258 default: |
| 259 break; |
| 260 } |
| 261 NOTREACHED(); |
| 262 return nullptr; |
| 263 } |
| 264 |
| 265 SVGPropertyBase* SVGAnimateElement::createPropertyForAnimation( |
| 266 const String& value) const { |
| 267 if (isAnimatingSVGDom()) |
| 268 return createPropertyForAttributeAnimation(value); |
| 269 DCHECK(isAnimatingCSSProperty()); |
| 270 return createPropertyForCSSAnimation(value); |
| 271 } |
| 272 |
163 SVGPropertyBase* SVGAnimateElement::adjustForInheritance( | 273 SVGPropertyBase* SVGAnimateElement::adjustForInheritance( |
164 SVGPropertyBase* propertyValue, | 274 SVGPropertyBase* propertyValue, |
165 AnimatedPropertyValueType valueType) const { | 275 AnimatedPropertyValueType valueType) const { |
166 if (valueType != InheritValue) | 276 if (valueType != InheritValue) |
167 return propertyValue; | 277 return propertyValue; |
168 // TODO(fs): At the moment the computed style gets returned as a String and | 278 // TODO(fs): At the moment the computed style gets returned as a String and |
169 // needs to get parsed again. In the future we might want to work with the | 279 // needs to get parsed again. In the future we might want to work with the |
170 // value type directly to avoid the String parsing. | 280 // value type directly to avoid the String parsing. |
171 DCHECK(targetElement()); | 281 DCHECK(targetElement()); |
172 Element* parent = targetElement()->parentElement(); | 282 Element* parent = targetElement()->parentElement(); |
173 if (!parent || !parent->isSVGElement()) | 283 if (!parent || !parent->isSVGElement()) |
174 return propertyValue; | 284 return propertyValue; |
175 SVGElement* svgParent = toSVGElement(parent); | 285 SVGElement* svgParent = toSVGElement(parent); |
176 // Replace 'inherit' by its computed property value. | 286 // Replace 'inherit' by its computed property value. |
177 String value = computeCSSPropertyValue(svgParent, m_animator.cssProperty()); | 287 String value = computeCSSPropertyValue(svgParent, m_cssPropertyId); |
178 return m_animator.createPropertyForAnimation(value); | 288 return createPropertyForAnimation(value); |
179 } | 289 } |
180 | 290 |
181 void SVGAnimateElement::calculateAnimatedValue(float percentage, | 291 void SVGAnimateElement::calculateAnimatedValue(float percentage, |
182 unsigned repeatCount, | 292 unsigned repeatCount, |
183 SVGSMILElement* resultElement) { | 293 SVGSMILElement* resultElement) { |
184 DCHECK(resultElement); | 294 DCHECK(resultElement); |
185 DCHECK(targetElement()); | 295 DCHECK(targetElement()); |
186 if (!isSVGAnimateElement(*resultElement)) | 296 if (!isSVGAnimateElement(*resultElement)) |
187 return; | 297 return; |
188 | 298 |
189 ASSERT(percentage >= 0 && percentage <= 1); | 299 DCHECK(percentage >= 0 && percentage <= 1); |
190 ASSERT(animatedPropertyType() != AnimatedTransformList || | 300 DCHECK_NE(animatedPropertyType(), AnimatedUnknown); |
191 isSVGAnimateTransformElement(*this)); | 301 DCHECK(m_fromProperty); |
192 ASSERT(animatedPropertyType() != AnimatedUnknown); | 302 DCHECK_EQ(m_fromProperty->type(), animatedPropertyType()); |
193 ASSERT(m_fromProperty); | 303 DCHECK(m_toProperty); |
194 ASSERT(m_fromProperty->type() == animatedPropertyType()); | |
195 ASSERT(m_toProperty); | |
196 | 304 |
197 SVGAnimateElement* resultAnimationElement = | 305 SVGAnimateElement* resultAnimationElement = |
198 toSVGAnimateElement(resultElement); | 306 toSVGAnimateElement(resultElement); |
199 ASSERT(resultAnimationElement->m_animatedProperty); | 307 DCHECK(resultAnimationElement->m_animatedValue); |
200 ASSERT(resultAnimationElement->animatedPropertyType() == | 308 DCHECK_EQ(resultAnimationElement->animatedPropertyType(), |
201 animatedPropertyType()); | 309 animatedPropertyType()); |
202 | 310 |
203 if (isSVGSetElement(*this)) | 311 if (isSVGSetElement(*this)) |
204 percentage = 1; | 312 percentage = 1; |
205 | 313 |
206 if (getCalcMode() == CalcModeDiscrete) | 314 if (getCalcMode() == CalcModeDiscrete) |
207 percentage = percentage < 0.5 ? 0 : 1; | 315 percentage = percentage < 0.5 ? 0 : 1; |
208 | 316 |
209 // Target element might have changed. | 317 // Target element might have changed. |
210 SVGElement* targetElement = this->targetElement(); | 318 SVGElement* targetElement = this->targetElement(); |
211 | 319 |
212 // Values-animation accumulates using the last values entry corresponding to | 320 // Values-animation accumulates using the last values entry corresponding to |
213 // the end of duration time. | 321 // the end of duration time. |
214 SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedProperty; | 322 SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedValue; |
215 SVGPropertyBase* toAtEndOfDurationValue = | 323 SVGPropertyBase* toAtEndOfDurationValue = |
216 m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty : m_toProperty; | 324 m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty : m_toProperty; |
217 SVGPropertyBase* fromValue = | 325 SVGPropertyBase* fromValue = |
218 getAnimationMode() == ToAnimation ? animatedValue : m_fromProperty.get(); | 326 getAnimationMode() == ToAnimation ? animatedValue : m_fromProperty.get(); |
219 SVGPropertyBase* toValue = m_toProperty; | 327 SVGPropertyBase* toValue = m_toProperty; |
220 | 328 |
221 // Apply CSS inheritance rules. | 329 // Apply CSS inheritance rules. |
222 fromValue = adjustForInheritance(fromValue, m_fromPropertyValueType); | 330 fromValue = adjustForInheritance(fromValue, m_fromPropertyValueType); |
223 toValue = adjustForInheritance(toValue, m_toPropertyValueType); | 331 toValue = adjustForInheritance(toValue, m_toPropertyValueType); |
224 | 332 |
225 animatedValue->calculateAnimatedValue(this, percentage, repeatCount, | 333 animatedValue->calculateAnimatedValue(this, percentage, repeatCount, |
226 fromValue, toValue, | 334 fromValue, toValue, |
227 toAtEndOfDurationValue, targetElement); | 335 toAtEndOfDurationValue, targetElement); |
228 } | 336 } |
229 | 337 |
230 bool SVGAnimateElement::calculateToAtEndOfDurationValue( | 338 bool SVGAnimateElement::calculateToAtEndOfDurationValue( |
231 const String& toAtEndOfDurationString) { | 339 const String& toAtEndOfDurationString) { |
232 if (toAtEndOfDurationString.isEmpty()) | 340 if (toAtEndOfDurationString.isEmpty()) |
233 return false; | 341 return false; |
234 m_toAtEndOfDurationProperty = | 342 m_toAtEndOfDurationProperty = |
235 m_animator.createPropertyForAnimation(toAtEndOfDurationString); | 343 createPropertyForAnimation(toAtEndOfDurationString); |
236 return true; | 344 return true; |
237 } | 345 } |
238 | 346 |
239 bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, | 347 bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, |
240 const String& toString) { | 348 const String& toString) { |
241 DCHECK(targetElement()); | 349 DCHECK(targetElement()); |
242 m_fromProperty = m_animator.createPropertyForAnimation(fromString); | 350 m_fromProperty = createPropertyForAnimation(fromString); |
243 m_fromPropertyValueType = propertyValueType(attributeName(), fromString); | 351 m_fromPropertyValueType = propertyValueType(attributeName(), fromString); |
244 m_toProperty = m_animator.createPropertyForAnimation(toString); | 352 m_toProperty = createPropertyForAnimation(toString); |
245 m_toPropertyValueType = propertyValueType(attributeName(), toString); | 353 m_toPropertyValueType = propertyValueType(attributeName(), toString); |
246 return true; | 354 return true; |
247 } | 355 } |
248 | 356 |
249 bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, | 357 bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, |
250 const String& byString) { | 358 const String& byString) { |
251 DCHECK(targetElement()); | 359 DCHECK(targetElement()); |
252 | 360 |
253 if (getAnimationMode() == ByAnimation && !isAdditive()) | 361 if (getAnimationMode() == ByAnimation && !isAdditive()) |
254 return false; | 362 return false; |
255 | 363 |
256 // from-by animation may only be used with attributes that support addition | 364 // from-by animation may only be used with attributes that support addition |
257 // (e.g. most numeric attributes). | 365 // (e.g. most numeric attributes). |
258 if (getAnimationMode() == FromByAnimation && | 366 if (getAnimationMode() == FromByAnimation && |
259 !animatedPropertyTypeSupportsAddition()) | 367 !animatedPropertyTypeSupportsAddition()) |
260 return false; | 368 return false; |
261 | 369 |
262 DCHECK(!isSVGSetElement(*this)); | 370 DCHECK(!isSVGSetElement(*this)); |
263 | 371 |
264 m_fromProperty = m_animator.createPropertyForAnimation(fromString); | 372 m_fromProperty = createPropertyForAnimation(fromString); |
265 m_fromPropertyValueType = propertyValueType(attributeName(), fromString); | 373 m_fromPropertyValueType = propertyValueType(attributeName(), fromString); |
266 m_toProperty = m_animator.createPropertyForAnimation(byString); | 374 m_toProperty = createPropertyForAnimation(byString); |
267 m_toPropertyValueType = propertyValueType(attributeName(), byString); | 375 m_toPropertyValueType = propertyValueType(attributeName(), byString); |
268 m_toProperty->add(m_fromProperty, targetElement()); | 376 m_toProperty->add(m_fromProperty, targetElement()); |
269 return true; | 377 return true; |
270 } | 378 } |
271 | 379 |
272 void SVGAnimateElement::resetAnimatedType() { | 380 void SVGAnimateElement::resetAnimatedType() { |
| 381 resolveTargetProperty(); |
| 382 |
273 SVGElement* targetElement = this->targetElement(); | 383 SVGElement* targetElement = this->targetElement(); |
274 const QualifiedName& attributeName = this->attributeName(); | 384 const QualifiedName& attributeName = this->attributeName(); |
275 | 385 |
276 m_animator.reset(*targetElement); | |
277 | |
278 if (!shouldApplyAnimation(*targetElement, attributeName)) | 386 if (!shouldApplyAnimation(*targetElement, attributeName)) |
279 return; | 387 return; |
280 if (m_animator.isAnimatingSVGDom()) { | 388 if (isAnimatingSVGDom()) { |
281 // SVG DOM animVal animation code-path. | 389 // SVG DOM animVal animation code-path. |
282 m_animatedProperty = m_animator.createAnimatedValue(); | 390 m_animatedValue = m_targetProperty->createAnimatedValue(); |
283 targetElement->setAnimatedAttribute(attributeName, m_animatedProperty); | 391 DCHECK_EQ(m_animatedValue->type(), m_type); |
| 392 targetElement->setAnimatedAttribute(attributeName, m_animatedValue); |
284 return; | 393 return; |
285 } | 394 } |
286 DCHECK(m_animator.isAnimatingCSSProperty()); | 395 DCHECK(isAnimatingCSSProperty()); |
287 // Presentation attributes which has an SVG DOM representation should use the | 396 // Presentation attributes which has an SVG DOM representation should use the |
288 // "SVG DOM" code-path (above.) | 397 // "SVG DOM" code-path (above.) |
289 DCHECK(SVGElement::isAnimatableCSSProperty(attributeName)); | 398 DCHECK(SVGElement::isAnimatableCSSProperty(attributeName)); |
290 | 399 |
291 // CSS properties animation code-path. | 400 // CSS properties animation code-path. |
292 String baseValue = | 401 String baseValue = computeCSSPropertyValue(targetElement, m_cssPropertyId); |
293 computeCSSPropertyValue(targetElement, m_animator.cssProperty()); | 402 m_animatedValue = createPropertyForAnimation(baseValue); |
294 m_animatedProperty = m_animator.createPropertyForAnimation(baseValue); | |
295 } | 403 } |
296 | 404 |
297 void SVGAnimateElement::clearAnimatedType() { | 405 void SVGAnimateElement::clearAnimatedType() { |
298 if (!m_animatedProperty) | 406 if (!m_animatedValue) |
299 return; | 407 return; |
300 | 408 |
301 // The animated property lock is held for the "result animation" (see | 409 // The animated property lock is held for the "result animation" (see |
302 // SMILTimeContainer::updateAnimations()) while we're processing an animation | 410 // SMILTimeContainer::updateAnimations()) while we're processing an animation |
303 // group. We will very likely crash later if we clear the animated type while | 411 // group. We will very likely crash later if we clear the animated type while |
304 // the lock is held. See crbug.com/581546. | 412 // the lock is held. See crbug.com/581546. |
305 DCHECK(!animatedTypeIsLocked()); | 413 DCHECK(!animatedTypeIsLocked()); |
306 | 414 |
307 SVGElement* targetElement = this->targetElement(); | 415 SVGElement* targetElement = this->targetElement(); |
308 if (!targetElement) { | 416 if (!targetElement) { |
309 m_animatedProperty.clear(); | 417 m_animatedValue.clear(); |
310 return; | 418 return; |
311 } | 419 } |
312 | 420 |
313 bool shouldApply = shouldApplyAnimation(*targetElement, attributeName()); | 421 bool shouldApply = shouldApplyAnimation(*targetElement, attributeName()); |
314 if (m_animator.isAnimatingCSSProperty()) { | 422 if (isAnimatingCSSProperty()) { |
315 // CSS properties animation code-path. | 423 // CSS properties animation code-path. |
316 if (shouldApply) { | 424 if (shouldApply) { |
317 MutableStylePropertySet* propertySet = | 425 MutableStylePropertySet* propertySet = |
318 targetElement->ensureAnimatedSMILStyleProperties(); | 426 targetElement->ensureAnimatedSMILStyleProperties(); |
319 if (propertySet->removeProperty(m_animator.cssProperty())) { | 427 if (propertySet->removeProperty(m_cssPropertyId)) { |
320 targetElement->setNeedsStyleRecalc( | 428 targetElement->setNeedsStyleRecalc( |
321 LocalStyleChange, | 429 LocalStyleChange, |
322 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); | 430 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); |
323 } | 431 } |
324 } | 432 } |
325 } | 433 } |
326 if (m_animator.isAnimatingSVGDom()) { | 434 if (isAnimatingSVGDom()) { |
327 // SVG DOM animVal animation code-path. | 435 // SVG DOM animVal animation code-path. |
328 targetElement->clearAnimatedAttribute(attributeName()); | 436 targetElement->clearAnimatedAttribute(attributeName()); |
329 if (shouldApply) | 437 if (shouldApply) |
330 targetElement->invalidateAnimatedAttribute(attributeName()); | 438 targetElement->invalidateAnimatedAttribute(attributeName()); |
331 } | 439 } |
332 | 440 |
333 m_animatedProperty.clear(); | 441 m_animatedValue.clear(); |
334 m_animator.clear(); | 442 clearTargetProperty(); |
335 } | 443 } |
336 | 444 |
337 void SVGAnimateElement::applyResultsToTarget() { | 445 void SVGAnimateElement::applyResultsToTarget() { |
338 ASSERT(animatedPropertyType() != AnimatedTransformList || | 446 DCHECK_NE(animatedPropertyType(), AnimatedUnknown); |
339 isSVGAnimateTransformElement(*this)); | |
340 ASSERT(animatedPropertyType() != AnimatedUnknown); | |
341 | 447 |
342 // Early exit if our animated type got destructed by a previous | 448 // Early exit if our animated type got destructed by a previous |
343 // endedActiveInterval(). | 449 // endedActiveInterval(). |
344 if (!m_animatedProperty) | 450 if (!m_animatedValue) |
345 return; | 451 return; |
346 | 452 |
347 if (!shouldApplyAnimation(*targetElement(), attributeName())) | 453 if (!shouldApplyAnimation(*targetElement(), attributeName())) |
348 return; | 454 return; |
349 | 455 |
350 // We do update the style and the animation property independent of each | 456 // We do update the style and the animation property independent of each |
351 // other. | 457 // other. |
352 if (m_animator.isAnimatingCSSProperty()) { | 458 if (isAnimatingCSSProperty()) { |
353 // CSS properties animation code-path. | 459 // CSS properties animation code-path. |
354 // Convert the result of the animation to a String and apply it as CSS | 460 // Convert the result of the animation to a String and apply it as CSS |
355 // property on the target. | 461 // property on the target. |
356 MutableStylePropertySet* propertySet = | 462 MutableStylePropertySet* propertySet = |
357 targetElement()->ensureAnimatedSMILStyleProperties(); | 463 targetElement()->ensureAnimatedSMILStyleProperties(); |
358 if (propertySet | 464 if (propertySet |
359 ->setProperty(m_animator.cssProperty(), | 465 ->setProperty(m_cssPropertyId, m_animatedValue->valueAsString(), |
360 m_animatedProperty->valueAsString(), false, 0) | 466 false, 0) |
361 .didChange) { | 467 .didChange) { |
362 targetElement()->setNeedsStyleRecalc( | 468 targetElement()->setNeedsStyleRecalc( |
363 LocalStyleChange, | 469 LocalStyleChange, |
364 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); | 470 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); |
365 } | 471 } |
366 } | 472 } |
367 if (m_animator.isAnimatingSVGDom()) { | 473 if (isAnimatingSVGDom()) { |
368 // SVG DOM animVal animation code-path. | 474 // SVG DOM animVal animation code-path. |
369 // At this point the SVG DOM values are already changed, unlike for CSS. | 475 // At this point the SVG DOM values are already changed, unlike for CSS. |
370 // We only have to trigger update notifications here. | 476 // We only have to trigger update notifications here. |
371 targetElement()->invalidateAnimatedAttribute(attributeName()); | 477 targetElement()->invalidateAnimatedAttribute(attributeName()); |
372 } | 478 } |
373 } | 479 } |
374 | 480 |
375 bool SVGAnimateElement::animatedPropertyTypeSupportsAddition() { | 481 bool SVGAnimateElement::animatedPropertyTypeSupportsAddition() { |
376 // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties. | 482 // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties. |
377 switch (animatedPropertyType()) { | 483 switch (animatedPropertyType()) { |
(...skipping 16 matching lines...) Expand all Loading... |
394 } | 500 } |
395 | 501 |
396 return SVGAnimationElement::isAdditive(); | 502 return SVGAnimationElement::isAdditive(); |
397 } | 503 } |
398 | 504 |
399 float SVGAnimateElement::calculateDistance(const String& fromString, | 505 float SVGAnimateElement::calculateDistance(const String& fromString, |
400 const String& toString) { | 506 const String& toString) { |
401 DCHECK(targetElement()); | 507 DCHECK(targetElement()); |
402 // FIXME: A return value of float is not enough to support paced animations on | 508 // FIXME: A return value of float is not enough to support paced animations on |
403 // lists. | 509 // lists. |
404 SVGPropertyBase* fromValue = | 510 SVGPropertyBase* fromValue = createPropertyForAnimation(fromString); |
405 m_animator.createPropertyForAnimation(fromString); | 511 SVGPropertyBase* toValue = createPropertyForAnimation(toString); |
406 SVGPropertyBase* toValue = m_animator.createPropertyForAnimation(toString); | |
407 return fromValue->calculateDistance(toValue, targetElement()); | 512 return fromValue->calculateDistance(toValue, targetElement()); |
408 } | 513 } |
409 | 514 |
410 void SVGAnimateElement::setTargetElement(SVGElement* target) { | 515 void SVGAnimateElement::setTargetElement(SVGElement* target) { |
411 SVGAnimationElement::setTargetElement(target); | 516 SVGAnimationElement::setTargetElement(target); |
412 checkInvalidCSSAttributeType(); | 517 checkInvalidCSSAttributeType(); |
413 resetAnimatedPropertyType(); | 518 resetAnimatedPropertyType(); |
414 } | 519 } |
415 | 520 |
416 void SVGAnimateElement::setAttributeName(const QualifiedName& attributeName) { | 521 void SVGAnimateElement::setAttributeName(const QualifiedName& attributeName) { |
(...skipping 27 matching lines...) Expand all Loading... |
444 if (!hasInvalidCSSAttributeType) | 549 if (!hasInvalidCSSAttributeType) |
445 schedule(); | 550 schedule(); |
446 } | 551 } |
447 | 552 |
448 // Clear values that may depend on the previous target. | 553 // Clear values that may depend on the previous target. |
449 if (targetElement()) | 554 if (targetElement()) |
450 clearAnimatedType(); | 555 clearAnimatedType(); |
451 } | 556 } |
452 | 557 |
453 void SVGAnimateElement::resetAnimatedPropertyType() { | 558 void SVGAnimateElement::resetAnimatedPropertyType() { |
454 ASSERT(!m_animatedProperty); | 559 DCHECK(!m_animatedValue); |
455 m_fromProperty.clear(); | 560 m_fromProperty.clear(); |
456 m_toProperty.clear(); | 561 m_toProperty.clear(); |
457 m_toAtEndOfDurationProperty.clear(); | 562 m_toAtEndOfDurationProperty.clear(); |
458 m_animator.clear(); | 563 clearTargetProperty(); |
459 } | 564 } |
460 | 565 |
461 DEFINE_TRACE(SVGAnimateElement) { | 566 DEFINE_TRACE(SVGAnimateElement) { |
462 visitor->trace(m_fromProperty); | 567 visitor->trace(m_fromProperty); |
463 visitor->trace(m_toProperty); | 568 visitor->trace(m_toProperty); |
464 visitor->trace(m_toAtEndOfDurationProperty); | 569 visitor->trace(m_toAtEndOfDurationProperty); |
465 visitor->trace(m_animatedProperty); | 570 visitor->trace(m_animatedValue); |
466 visitor->trace(m_animator); | 571 visitor->trace(m_targetProperty); |
467 SVGAnimationElement::trace(visitor); | 572 SVGAnimationElement::trace(visitor); |
468 } | 573 } |
469 | 574 |
470 } // namespace blink | 575 } // namespace blink |
OLD | NEW |