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. |
(...skipping 10 matching lines...) Expand all Loading... |
21 */ | 21 */ |
22 | 22 |
23 #include "config.h" | 23 #include "config.h" |
24 | 24 |
25 #include "core/svg/SVGAnimateElement.h" | 25 #include "core/svg/SVGAnimateElement.h" |
26 | 26 |
27 #include "CSSPropertyNames.h" | 27 #include "CSSPropertyNames.h" |
28 #include "core/css/parser/BisonCSSParser.h" | 28 #include "core/css/parser/BisonCSSParser.h" |
29 #include "core/css/StylePropertySet.h" | 29 #include "core/css/StylePropertySet.h" |
30 #include "core/dom/QualifiedName.h" | 30 #include "core/dom/QualifiedName.h" |
31 #include "core/svg/SVGAnimatedType.h" | |
32 #include "core/svg/SVGAnimatedTypeAnimator.h" | 31 #include "core/svg/SVGAnimatedTypeAnimator.h" |
33 #include "core/svg/SVGAnimatorFactory.h" | 32 #include "core/svg/SVGAnimatorFactory.h" |
34 #include "core/svg/SVGDocumentExtensions.h" | 33 #include "core/svg/SVGDocumentExtensions.h" |
35 | 34 |
36 namespace WebCore { | 35 namespace WebCore { |
37 | 36 |
38 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, Document& doc
ument) | 37 SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName, Document& doc
ument) |
39 : SVGAnimationElement(tagName, document) | 38 : SVGAnimationElement(tagName, document) |
40 , m_animatedPropertyType(AnimatedString) | 39 , m_animatedPropertyType(AnimatedString) |
41 { | 40 { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 if (!targetElement || !isSVGAnimateElement(*resultElement)) | 92 if (!targetElement || !isSVGAnimateElement(*resultElement)) |
94 return; | 93 return; |
95 | 94 |
96 ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(targetElement
)); | 95 ASSERT(m_animatedPropertyType == determineAnimatedPropertyType(targetElement
)); |
97 | 96 |
98 ASSERT(percentage >= 0 && percentage <= 1); | 97 ASSERT(percentage >= 0 && percentage <= 1); |
99 ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGName
s::animateTransformTag)); | 98 ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGName
s::animateTransformTag)); |
100 ASSERT(m_animatedPropertyType != AnimatedUnknown); | 99 ASSERT(m_animatedPropertyType != AnimatedUnknown); |
101 ASSERT(m_animator); | 100 ASSERT(m_animator); |
102 ASSERT(m_animator->type() == m_animatedPropertyType); | 101 ASSERT(m_animator->type() == m_animatedPropertyType); |
103 ASSERT(m_fromType); | 102 ASSERT(m_fromProperty); |
104 ASSERT(m_fromType->type() == m_animatedPropertyType); | 103 ASSERT(m_fromProperty->type() == m_animatedPropertyType); |
105 ASSERT(m_toType); | 104 ASSERT(m_toProperty); |
106 | 105 |
107 SVGAnimateElement* resultAnimationElement = toSVGAnimateElement(resultElemen
t); | 106 SVGAnimateElement* resultAnimationElement = toSVGAnimateElement(resultElemen
t); |
108 ASSERT(resultAnimationElement->m_animatedType); | 107 ASSERT(resultAnimationElement->m_animatedProperty); |
109 ASSERT(resultAnimationElement->m_animatedPropertyType == m_animatedPropertyT
ype); | 108 ASSERT(resultAnimationElement->m_animatedPropertyType == m_animatedPropertyT
ype); |
110 | 109 |
111 if (hasTagName(SVGNames::setTag)) | 110 if (hasTagName(SVGNames::setTag)) |
112 percentage = 1; | 111 percentage = 1; |
113 | 112 |
114 if (calcMode() == CalcModeDiscrete) | 113 if (calcMode() == CalcModeDiscrete) |
115 percentage = percentage < 0.5 ? 0 : 1; | 114 percentage = percentage < 0.5 ? 0 : 1; |
116 | 115 |
117 // Target element might have changed. | 116 // Target element might have changed. |
118 m_animator->setContextElement(targetElement); | 117 m_animator->setContextElement(targetElement); |
119 | 118 |
120 // Be sure to detach list wrappers before we modfiy their underlying value.
If we'd do | 119 // Be sure to detach list wrappers before we modfiy their underlying value.
If we'd do |
121 // if after calculateAnimatedValue() ran the cached pointers in the list pro
pery tear | 120 // if after calculateAnimatedValue() ran the cached pointers in the list pro
pery tear |
122 // offs would point nowhere, and we couldn't create copies of those values a
nymore, | 121 // offs would point nowhere, and we couldn't create copies of those values a
nymore, |
123 // while detaching. This is covered by assertions, moving this down would fi
re them. | 122 // while detaching. This is covered by assertions, moving this down would fi
re them. |
124 if (!m_animatedProperties.isEmpty()) | 123 if (!m_animatedProperties.isEmpty()) |
125 m_animator->animValWillChange(m_animatedProperties); | 124 m_animator->animValWillChange(m_animatedProperties); |
126 | 125 |
127 // Values-animation accumulates using the last values entry corresponding to
the end of duration time. | 126 // Values-animation accumulates using the last values entry corresponding to
the end of duration time. |
128 SVGAnimatedType* toAtEndOfDurationType = m_toAtEndOfDurationType ? m_toAtEnd
OfDurationType.get() : m_toType.get(); | 127 NewSVGPropertyBase* toAtEndOfDurationProperty = m_toAtEndOfDurationProperty
? m_toAtEndOfDurationProperty.get() : m_toProperty.get(); |
129 m_animator->calculateAnimatedValue(percentage, repeatCount, m_fromType.get()
, m_toType.get(), toAtEndOfDurationType, resultAnimationElement->m_animatedType.
get()); | 128 m_animator->calculateAnimatedValue(percentage, repeatCount, m_fromProperty.g
et(), m_toProperty.get(), toAtEndOfDurationProperty, resultAnimationElement->m_a
nimatedProperty.get()); |
130 } | 129 } |
131 | 130 |
132 bool SVGAnimateElement::calculateToAtEndOfDurationValue(const String& toAtEndOfD
urationString) | 131 bool SVGAnimateElement::calculateToAtEndOfDurationValue(const String& toAtEndOfD
urationString) |
133 { | 132 { |
134 if (toAtEndOfDurationString.isEmpty()) | 133 if (toAtEndOfDurationString.isEmpty()) |
135 return false; | 134 return false; |
136 m_toAtEndOfDurationType = ensureAnimator()->constructFromString(toAtEndOfDur
ationString); | 135 m_toAtEndOfDurationProperty = ensureAnimator()->constructFromString(toAtEndO
fDurationString); |
137 return true; | 136 return true; |
138 } | 137 } |
139 | 138 |
140 bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
String& toString) | 139 bool SVGAnimateElement::calculateFromAndToValues(const String& fromString, const
String& toString) |
141 { | 140 { |
142 SVGElement* targetElement = this->targetElement(); | 141 SVGElement* targetElement = this->targetElement(); |
143 if (!targetElement) | 142 if (!targetElement) |
144 return false; | 143 return false; |
145 | 144 |
146 determinePropertyValueTypes(fromString, toString); | 145 determinePropertyValueTypes(fromString, toString); |
147 ensureAnimator()->calculateFromAndToValues(m_fromType, m_toType, fromString,
toString); | 146 ensureAnimator()->calculateFromAndToValues(m_fromProperty, m_toProperty, fro
mString, toString); |
148 ASSERT(m_animatedPropertyType == m_animator->type()); | 147 ASSERT(m_animatedPropertyType == m_animator->type()); |
149 return true; | 148 return true; |
150 } | 149 } |
151 | 150 |
152 bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const
String& byString) | 151 bool SVGAnimateElement::calculateFromAndByValues(const String& fromString, const
String& byString) |
153 { | 152 { |
154 SVGElement* targetElement = this->targetElement(); | 153 SVGElement* targetElement = this->targetElement(); |
155 if (!targetElement) | 154 if (!targetElement) |
156 return false; | 155 return false; |
157 | 156 |
158 if (animationMode() == ByAnimation && !isAdditive()) | 157 if (animationMode() == ByAnimation && !isAdditive()) |
159 return false; | 158 return false; |
160 | 159 |
161 // from-by animation may only be used with attributes that support addition
(e.g. most numeric attributes). | 160 // from-by animation may only be used with attributes that support addition
(e.g. most numeric attributes). |
162 if (animationMode() == FromByAnimation && !animatedPropertyTypeSupportsAddit
ion()) | 161 if (animationMode() == FromByAnimation && !animatedPropertyTypeSupportsAddit
ion()) |
163 return false; | 162 return false; |
164 | 163 |
165 ASSERT(!hasTagName(SVGNames::setTag)); | 164 ASSERT(!hasTagName(SVGNames::setTag)); |
166 | 165 |
167 determinePropertyValueTypes(fromString, byString); | 166 determinePropertyValueTypes(fromString, byString); |
168 ensureAnimator()->calculateFromAndByValues(m_fromType, m_toType, fromString,
byString); | 167 ensureAnimator()->calculateFromAndByValues(m_fromProperty, m_toProperty, fro
mString, byString); |
169 ASSERT(m_animatedPropertyType == m_animator->type()); | 168 ASSERT(m_animatedPropertyType == m_animator->type()); |
170 return true; | 169 return true; |
171 } | 170 } |
172 | 171 |
173 #ifndef NDEBUG | 172 #ifndef NDEBUG |
174 static inline bool propertyTypesAreConsistent(AnimatedPropertyType expectedPrope
rtyType, const SVGElementAnimatedPropertyList& animatedTypes) | 173 static inline bool propertyTypesAreConsistent(AnimatedPropertyType expectedPrope
rtyType, const SVGElementAnimatedPropertyList& animatedTypes) |
175 { | 174 { |
176 SVGElementAnimatedPropertyList::const_iterator end = animatedTypes.end(); | 175 SVGElementAnimatedPropertyList::const_iterator end = animatedTypes.end(); |
177 for (SVGElementAnimatedPropertyList::const_iterator it = animatedTypes.begin
(); it != end; ++it) { | 176 for (SVGElementAnimatedPropertyList::const_iterator it = animatedTypes.begin
(); it != end; ++it) { |
178 for (size_t i = 0; i < it->properties.size(); ++i) { | 177 for (size_t i = 0; i < it->properties.size(); ++i) { |
(...skipping 25 matching lines...) Expand all Loading... |
204 if (shouldApply == ApplyXMLAnimation) { | 203 if (shouldApply == ApplyXMLAnimation) { |
205 // SVG DOM animVal animation code-path. | 204 // SVG DOM animVal animation code-path. |
206 m_animatedProperties = animator->findAnimatedPropertiesForAttributeName(
targetElement, attributeName); | 205 m_animatedProperties = animator->findAnimatedPropertiesForAttributeName(
targetElement, attributeName); |
207 SVGElementAnimatedPropertyList::const_iterator end = m_animatedPropertie
s.end(); | 206 SVGElementAnimatedPropertyList::const_iterator end = m_animatedPropertie
s.end(); |
208 for (SVGElementAnimatedPropertyList::const_iterator it = m_animatedPrope
rties.begin(); it != end; ++it) | 207 for (SVGElementAnimatedPropertyList::const_iterator it = m_animatedPrope
rties.begin(); it != end; ++it) |
209 document().accessSVGExtensions().addElementReferencingTarget(this, i
t->element); | 208 document().accessSVGExtensions().addElementReferencingTarget(this, i
t->element); |
210 | 209 |
211 ASSERT(!m_animatedProperties.isEmpty()); | 210 ASSERT(!m_animatedProperties.isEmpty()); |
212 | 211 |
213 ASSERT(propertyTypesAreConsistent(m_animatedPropertyType, m_animatedProp
erties)); | 212 ASSERT(propertyTypesAreConsistent(m_animatedPropertyType, m_animatedProp
erties)); |
214 if (!m_animatedType) | 213 if (!m_animatedProperty) |
215 m_animatedType = animator->startAnimValAnimation(m_animatedPropertie
s); | 214 m_animatedProperty = animator->startAnimValAnimation(m_animatedPrope
rties); |
216 else { | 215 else { |
217 animator->resetAnimValToBaseVal(m_animatedProperties, m_animatedType
.get()); | 216 m_animatedProperty = animator->resetAnimValToBaseVal(m_animatedPrope
rties); |
218 animator->animValDidChange(m_animatedProperties); | 217 animator->animValDidChange(m_animatedProperties); |
219 } | 218 } |
220 return; | 219 return; |
221 } | 220 } |
222 | 221 |
223 // CSS properties animation code-path. | 222 // CSS properties animation code-path. |
224 ASSERT(m_animatedProperties.isEmpty()); | 223 ASSERT(m_animatedProperties.isEmpty()); |
225 String baseValue; | 224 String baseValue; |
226 | 225 |
227 if (shouldApply == ApplyCSSAnimation) { | 226 if (shouldApply == ApplyCSSAnimation) { |
228 ASSERT(SVGAnimationElement::isTargetAttributeCSSProperty(targetElement,
attributeName)); | 227 ASSERT(SVGAnimationElement::isTargetAttributeCSSProperty(targetElement,
attributeName)); |
229 computeCSSPropertyValue(targetElement, cssPropertyID(attributeName.local
Name()), baseValue); | 228 computeCSSPropertyValue(targetElement, cssPropertyID(attributeName.local
Name()), baseValue); |
230 } | 229 } |
231 | 230 |
232 if (!m_animatedType || !m_animatedType->setValueAsString(attributeName, base
Value)) | 231 if (!m_animatedProperty) |
233 m_animatedType = animator->constructFromString(baseValue); | 232 m_animatedProperty = animator->constructFromString(baseValue); |
234 } | 233 } |
235 | 234 |
236 static inline void applyCSSPropertyToTarget(SVGElement* targetElement, CSSProper
tyID id, const String& value) | 235 static inline void applyCSSPropertyToTarget(SVGElement* targetElement, CSSProper
tyID id, const String& value) |
237 { | 236 { |
238 ASSERT_WITH_SECURITY_IMPLICATION(!targetElement->m_deletionHasBegun); | 237 ASSERT_WITH_SECURITY_IMPLICATION(!targetElement->m_deletionHasBegun); |
239 | 238 |
240 MutableStylePropertySet* propertySet = targetElement->ensureAnimatedSMILStyl
eProperties(); | 239 MutableStylePropertySet* propertySet = targetElement->ensureAnimatedSMILStyl
eProperties(); |
241 if (!propertySet->setProperty(id, value, false, 0)) | 240 if (!propertySet->setProperty(id, value, false, 0)) |
242 return; | 241 return; |
243 | 242 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 const HashSet<SVGElementInstance*>& instances = targetElement->instancesForE
lement(); | 310 const HashSet<SVGElementInstance*>& instances = targetElement->instancesForE
lement(); |
312 const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); | 311 const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); |
313 for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it
!= end; ++it) { | 312 for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it
!= end; ++it) { |
314 if (SVGElement* shadowTreeElement = (*it)->shadowTreeElement()) | 313 if (SVGElement* shadowTreeElement = (*it)->shadowTreeElement()) |
315 notifyTargetAboutAnimValChange(shadowTreeElement, attributeName); | 314 notifyTargetAboutAnimValChange(shadowTreeElement, attributeName); |
316 } | 315 } |
317 } | 316 } |
318 | 317 |
319 void SVGAnimateElement::clearAnimatedType(SVGElement* targetElement) | 318 void SVGAnimateElement::clearAnimatedType(SVGElement* targetElement) |
320 { | 319 { |
321 if (!m_animatedType) | 320 if (!m_animatedProperty) |
322 return; | 321 return; |
323 | 322 |
324 if (!targetElement) { | 323 if (!targetElement) { |
325 m_animatedType.clear(); | 324 m_animatedProperty.clear(); |
326 return; | 325 return; |
327 } | 326 } |
328 | 327 |
329 if (m_animatedProperties.isEmpty()) { | 328 if (m_animatedProperties.isEmpty()) { |
330 // CSS properties animation code-path. | 329 // CSS properties animation code-path. |
331 removeCSSPropertyFromTargetAndInstances(targetElement, attributeName()); | 330 removeCSSPropertyFromTargetAndInstances(targetElement, attributeName()); |
332 m_animatedType.clear(); | 331 m_animatedProperty.clear(); |
333 return; | 332 return; |
334 } | 333 } |
335 | 334 |
336 // SVG DOM animVal animation code-path. | 335 // SVG DOM animVal animation code-path. |
337 if (m_animator) { | 336 if (m_animator) { |
338 m_animator->stopAnimValAnimation(m_animatedProperties); | 337 m_animator->stopAnimValAnimation(m_animatedProperties); |
339 notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName(
)); | 338 notifyTargetAndInstancesAboutAnimValChange(targetElement, attributeName(
)); |
340 } | 339 } |
341 | 340 |
342 m_animatedProperties.clear(); | 341 m_animatedProperties.clear(); |
343 m_animatedType.clear(); | 342 m_animatedProperty.clear(); |
344 } | 343 } |
345 | 344 |
346 void SVGAnimateElement::applyResultsToTarget() | 345 void SVGAnimateElement::applyResultsToTarget() |
347 { | 346 { |
348 ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGName
s::animateTransformTag)); | 347 ASSERT(m_animatedPropertyType != AnimatedTransformList || hasTagName(SVGName
s::animateTransformTag)); |
349 ASSERT(m_animatedPropertyType != AnimatedUnknown); | 348 ASSERT(m_animatedPropertyType != AnimatedUnknown); |
350 ASSERT(m_animator); | 349 ASSERT(m_animator); |
351 | 350 |
352 // Early exit if our animated type got destructed by a previous endedActiveI
nterval(). | 351 // Early exit if our animated type got destructed by a previous endedActiveI
nterval(). |
353 if (!m_animatedType) | 352 if (!m_animatedProperty) |
354 return; | 353 return; |
355 | 354 |
356 if (m_animatedProperties.isEmpty()) { | 355 if (m_animatedProperties.isEmpty()) { |
357 // CSS properties animation code-path. | 356 // CSS properties animation code-path. |
358 // Convert the result of the animation to a String and apply it as CSS p
roperty on the target & all instances. | 357 // Convert the result of the animation to a String and apply it as CSS p
roperty on the target & all instances. |
359 applyCSSPropertyToTargetAndInstances(targetElement(), attributeName(), m
_animatedType->valueAsString()); | 358 applyCSSPropertyToTargetAndInstances(targetElement(), attributeName(), m
_animatedProperty->valueAsString()); |
360 return; | 359 return; |
361 } | 360 } |
362 | 361 |
363 // SVG DOM animVal animation code-path. | 362 // SVG DOM animVal animation code-path. |
364 // At this point the SVG DOM values are already changed, unlike for CSS. | 363 // At this point the SVG DOM values are already changed, unlike for CSS. |
365 // We only have to trigger update notifications here. | 364 // We only have to trigger update notifications here. |
366 m_animator->animValDidChange(m_animatedProperties); | 365 m_animator->animValDidChange(m_animatedProperties); |
367 notifyTargetAndInstancesAboutAnimValChange(targetElement(), attributeName())
; | 366 notifyTargetAndInstancesAboutAnimValChange(targetElement(), attributeName())
; |
368 } | 367 } |
369 | 368 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 } | 407 } |
409 | 408 |
410 void SVGAnimateElement::setAttributeName(const QualifiedName& attributeName) | 409 void SVGAnimateElement::setAttributeName(const QualifiedName& attributeName) |
411 { | 410 { |
412 SVGAnimationElement::setAttributeName(attributeName); | 411 SVGAnimationElement::setAttributeName(attributeName); |
413 resetAnimatedPropertyType(); | 412 resetAnimatedPropertyType(); |
414 } | 413 } |
415 | 414 |
416 void SVGAnimateElement::resetAnimatedPropertyType() | 415 void SVGAnimateElement::resetAnimatedPropertyType() |
417 { | 416 { |
418 ASSERT(!m_animatedType); | 417 ASSERT(!m_animatedProperty); |
419 m_fromType.clear(); | 418 m_fromProperty.clear(); |
420 m_toType.clear(); | 419 m_toProperty.clear(); |
421 m_toAtEndOfDurationType.clear(); | 420 m_toAtEndOfDurationProperty.clear(); |
422 m_animator.clear(); | 421 m_animator.clear(); |
423 m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(tar
getElement()) : AnimatedString; | 422 m_animatedPropertyType = targetElement() ? determineAnimatedPropertyType(tar
getElement()) : AnimatedString; |
424 } | 423 } |
425 | 424 |
426 SVGAnimatedTypeAnimator* SVGAnimateElement::ensureAnimator() | 425 SVGAnimatedTypeAnimator* SVGAnimateElement::ensureAnimator() |
427 { | 426 { |
428 if (!m_animator) | 427 if (!m_animator) |
429 m_animator = SVGAnimatorFactory::create(this, targetElement(), m_animate
dPropertyType); | 428 m_animator = SVGAnimatorFactory::create(this, targetElement(), m_animate
dPropertyType); |
430 ASSERT(m_animatedPropertyType == m_animator->type()); | 429 ASSERT(m_animatedPropertyType == m_animator->type()); |
431 return m_animator.get(); | 430 return m_animator.get(); |
432 } | 431 } |
433 | 432 |
434 } | 433 } |
OLD | NEW |