Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp

Issue 2496583002: Refactor CSS property mapping for SMIL Animation (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/CSSPropertyNames.h"
26 #include "core/css/CSSComputedStyleDeclaration.h" 25 #include "core/css/CSSComputedStyleDeclaration.h"
27 #include "core/css/StylePropertySet.h" 26 #include "core/css/StylePropertySet.h"
28 #include "core/dom/Document.h" 27 #include "core/dom/Document.h"
29 #include "core/dom/QualifiedName.h" 28 #include "core/dom/QualifiedName.h"
30 #include "core/dom/StyleChangeReason.h" 29 #include "core/dom/StyleChangeReason.h"
31 #include "core/svg/properties/SVGProperty.h" 30 #include "core/svg/properties/SVGProperty.h"
32 31
33 namespace blink { 32 namespace blink {
34 33
35 namespace { 34 namespace {
36 35
37 bool isTargetAttributeCSSProperty(SVGElement& targetElement, 36 bool isTargetAttributeCSSProperty(const SVGElement& targetElement,
38 const QualifiedName& attributeName) { 37 const QualifiedName& attributeName) {
39 return SVGElement::isAnimatableCSSProperty(attributeName) || 38 return SVGElement::isAnimatableCSSProperty(attributeName) ||
40 targetElement.isPresentationAttribute(attributeName); 39 targetElement.isPresentationAttribute(attributeName);
41 } 40 }
42 41
43 String computeCSSPropertyValue(SVGElement* element, CSSPropertyID id) { 42 String computeCSSPropertyValue(SVGElement* element, CSSPropertyID id) {
44 DCHECK(element); 43 DCHECK(element);
45 // TODO(fs): StyleEngine doesn't support document without a frame. 44 // TODO(fs): StyleEngine doesn't support document without a frame.
46 // Refer to comment in Element::computedStyle. 45 // Refer to comment in Element::computedStyle.
47 DCHECK(element->inActiveDocument()); 46 DCHECK(element->inActiveDocument());
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 animationAttributeChanged(); 117 animationAttributeChanged();
119 return; 118 return;
120 } 119 }
121 SVGAnimationElement::svgAttributeChanged(attrName); 120 SVGAnimationElement::svgAttributeChanged(attrName);
122 } 121 }
123 122
124 AnimatedPropertyType SVGAnimateElement::animatedPropertyType() { 123 AnimatedPropertyType SVGAnimateElement::animatedPropertyType() {
125 if (!targetElement()) 124 if (!targetElement())
126 return AnimatedUnknown; 125 return AnimatedUnknown;
127 126
128 m_animator.reset(targetElement()); 127 m_animator.reset(*targetElement());
129 return m_animator.type(); 128 return m_animator.type();
130 } 129 }
131 130
132 bool SVGAnimateElement::hasValidTarget() { 131 bool SVGAnimateElement::hasValidTarget() {
133 return SVGAnimationElement::hasValidTarget() && hasValidAttributeName() && 132 return SVGAnimationElement::hasValidTarget() && hasValidAttributeName() &&
134 hasValidAttributeType(); 133 hasValidAttributeType();
135 } 134 }
136 135
137 bool SVGAnimateElement::hasValidAttributeName() const { 136 bool SVGAnimateElement::hasValidAttributeName() const {
138 return attributeName() != anyQName(); 137 return attributeName() != anyQName();
139 } 138 }
140 139
141 bool SVGAnimateElement::hasValidAttributeType() { 140 bool SVGAnimateElement::hasValidAttributeType() {
142 if (!targetElement()) 141 if (!targetElement())
143 return false; 142 return false;
144 return animatedPropertyType() != AnimatedUnknown && 143 return animatedPropertyType() != AnimatedUnknown &&
145 !hasInvalidCSSAttributeType(); 144 !hasInvalidCSSAttributeType();
146 } 145 }
147 146
148 SVGAnimateElement::ShouldApplyAnimationType 147 bool SVGAnimateElement::shouldApplyAnimation(
149 SVGAnimateElement::shouldApplyAnimation(SVGElement* targetElement, 148 const SVGElement& targetElement,
150 const QualifiedName& attributeName) { 149 const QualifiedName& attributeName) {
151 if (!hasValidTarget() || !targetElement->parentNode()) 150 if (!hasValidTarget() || !targetElement.parentNode())
152 return DontApplyAnimation; 151 return false;
153 152
154 // Always animate CSS properties using the ApplyCSSAnimation code path, 153 // Always animate CSS properties using the ApplyCSSAnimation code path,
155 // regardless of the attributeType value. 154 // regardless of the attributeType value.
156 if (isTargetAttributeCSSProperty(*targetElement, attributeName)) { 155 if (isTargetAttributeCSSProperty(targetElement, attributeName))
157 if (targetElement->isPresentationAttributeWithSVGDOM(attributeName)) 156 return true;
158 return ApplyXMLandCSSAnimation;
159 157
160 return ApplyCSSAnimation;
161 }
162 // If attributeType="CSS" and attributeName doesn't point to a CSS property, 158 // If attributeType="CSS" and attributeName doesn't point to a CSS property,
163 // ignore the animation. 159 // ignore the animation.
164 if (getAttributeType() == AttributeTypeCSS) 160 return getAttributeType() != AttributeTypeCSS;
165 return DontApplyAnimation;
166
167 return ApplyXMLAnimation;
168 } 161 }
169 162
170 SVGPropertyBase* SVGAnimateElement::adjustForInheritance( 163 SVGPropertyBase* SVGAnimateElement::adjustForInheritance(
171 SVGPropertyBase* propertyValue, 164 SVGPropertyBase* propertyValue,
172 AnimatedPropertyValueType valueType) const { 165 AnimatedPropertyValueType valueType) const {
173 if (valueType != InheritValue) 166 if (valueType != InheritValue)
174 return propertyValue; 167 return propertyValue;
175 // TODO(fs): At the moment the computed style gets returned as a String and 168 // TODO(fs): At the moment the computed style gets returned as a String and
176 // needs to get parsed again. In the future we might want to work with the 169 // needs to get parsed again. In the future we might want to work with the
177 // value type directly to avoid the String parsing. 170 // value type directly to avoid the String parsing.
178 DCHECK(targetElement()); 171 DCHECK(targetElement());
179 Element* parent = targetElement()->parentElement(); 172 Element* parent = targetElement()->parentElement();
180 if (!parent || !parent->isSVGElement()) 173 if (!parent || !parent->isSVGElement())
181 return propertyValue; 174 return propertyValue;
182 SVGElement* svgParent = toSVGElement(parent); 175 SVGElement* svgParent = toSVGElement(parent);
183 // Replace 'inherit' by its computed property value. 176 // Replace 'inherit' by its computed property value.
184 String value = computeCSSPropertyValue( 177 String value = computeCSSPropertyValue(svgParent, m_animator.cssProperty());
185 svgParent, cssPropertyID(attributeName().localName()));
186 return m_animator.createPropertyForAnimation(value); 178 return m_animator.createPropertyForAnimation(value);
187 } 179 }
188 180
189 void SVGAnimateElement::calculateAnimatedValue(float percentage, 181 void SVGAnimateElement::calculateAnimatedValue(float percentage,
190 unsigned repeatCount, 182 unsigned repeatCount,
191 SVGSMILElement* resultElement) { 183 SVGSMILElement* resultElement) {
192 DCHECK(resultElement); 184 DCHECK(resultElement);
193 DCHECK(targetElement()); 185 DCHECK(targetElement());
194 if (!isSVGAnimateElement(*resultElement)) 186 if (!isSVGAnimateElement(*resultElement))
195 return; 187 return;
(...skipping 13 matching lines...) Expand all
209 animatedPropertyType()); 201 animatedPropertyType());
210 202
211 if (isSVGSetElement(*this)) 203 if (isSVGSetElement(*this))
212 percentage = 1; 204 percentage = 1;
213 205
214 if (getCalcMode() == CalcModeDiscrete) 206 if (getCalcMode() == CalcModeDiscrete)
215 percentage = percentage < 0.5 ? 0 : 1; 207 percentage = percentage < 0.5 ? 0 : 1;
216 208
217 // Target element might have changed. 209 // Target element might have changed.
218 SVGElement* targetElement = this->targetElement(); 210 SVGElement* targetElement = this->targetElement();
219 m_animator.setContextElement(targetElement);
220 211
221 // Values-animation accumulates using the last values entry corresponding to 212 // Values-animation accumulates using the last values entry corresponding to
222 // the end of duration time. 213 // the end of duration time.
223 SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedProperty; 214 SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedProperty;
224 SVGPropertyBase* toAtEndOfDurationValue = 215 SVGPropertyBase* toAtEndOfDurationValue =
225 m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty : m_toProperty; 216 m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty : m_toProperty;
226 SVGPropertyBase* fromValue = 217 SVGPropertyBase* fromValue =
227 getAnimationMode() == ToAnimation ? animatedValue : m_fromProperty.get(); 218 getAnimationMode() == ToAnimation ? animatedValue : m_fromProperty.get();
228 SVGPropertyBase* toValue = m_toProperty; 219 SVGPropertyBase* toValue = m_toProperty;
229 220
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 m_toProperty = m_animator.createPropertyForAnimation(byString); 266 m_toProperty = m_animator.createPropertyForAnimation(byString);
276 m_toPropertyValueType = propertyValueType(attributeName(), byString); 267 m_toPropertyValueType = propertyValueType(attributeName(), byString);
277 m_toProperty->add(m_fromProperty, targetElement()); 268 m_toProperty->add(m_fromProperty, targetElement());
278 return true; 269 return true;
279 } 270 }
280 271
281 void SVGAnimateElement::resetAnimatedType() { 272 void SVGAnimateElement::resetAnimatedType() {
282 SVGElement* targetElement = this->targetElement(); 273 SVGElement* targetElement = this->targetElement();
283 const QualifiedName& attributeName = this->attributeName(); 274 const QualifiedName& attributeName = this->attributeName();
284 275
285 m_animator.reset(targetElement); 276 m_animator.reset(*targetElement);
286 277
287 ShouldApplyAnimationType shouldApply = 278 if (!shouldApplyAnimation(*targetElement, attributeName))
288 shouldApplyAnimation(targetElement, attributeName);
289 if (shouldApply == DontApplyAnimation)
290 return; 279 return;
291 if (shouldApply == ApplyXMLAnimation || 280 if (m_animator.isAnimatingSVGDom()) {
292 shouldApply == ApplyXMLandCSSAnimation) {
293 // SVG DOM animVal animation code-path. 281 // SVG DOM animVal animation code-path.
294 m_animatedProperty = m_animator.createAnimatedValue(); 282 m_animatedProperty = m_animator.createAnimatedValue();
295 targetElement->setAnimatedAttribute(attributeName, m_animatedProperty); 283 targetElement->setAnimatedAttribute(attributeName, m_animatedProperty);
296 return; 284 return;
297 } 285 }
298 DCHECK_EQ(shouldApply, ApplyCSSAnimation); 286 DCHECK(m_animator.isAnimatingCSSProperty());
287 // Presentation attributes which has an SVG DOM representation should use the
288 // "SVG DOM" code-path (above.)
289 DCHECK(SVGElement::isAnimatableCSSProperty(attributeName));
299 290
300 // CSS properties animation code-path. 291 // CSS properties animation code-path.
301 DCHECK(isTargetAttributeCSSProperty(*targetElement, attributeName)); 292 String baseValue =
302 String baseValue = computeCSSPropertyValue( 293 computeCSSPropertyValue(targetElement, m_animator.cssProperty());
303 targetElement, cssPropertyID(attributeName.localName()));
304 m_animatedProperty = m_animator.createPropertyForAnimation(baseValue); 294 m_animatedProperty = m_animator.createPropertyForAnimation(baseValue);
305 } 295 }
306 296
307 void SVGAnimateElement::clearAnimatedType() { 297 void SVGAnimateElement::clearAnimatedType() {
308 if (!m_animatedProperty) 298 if (!m_animatedProperty)
309 return; 299 return;
310 300
311 // The animated property lock is held for the "result animation" (see 301 // The animated property lock is held for the "result animation" (see
312 // SMILTimeContainer::updateAnimations()) while we're processing an animation 302 // SMILTimeContainer::updateAnimations()) while we're processing an animation
313 // group. We will very likely crash later if we clear the animated type while 303 // group. We will very likely crash later if we clear the animated type while
314 // the lock is held. See crbug.com/581546. 304 // the lock is held. See crbug.com/581546.
315 DCHECK(!animatedTypeIsLocked()); 305 DCHECK(!animatedTypeIsLocked());
316 306
317 SVGElement* targetElement = this->targetElement(); 307 SVGElement* targetElement = this->targetElement();
318 if (!targetElement) { 308 if (!targetElement) {
319 m_animatedProperty.clear(); 309 m_animatedProperty.clear();
320 return; 310 return;
321 } 311 }
322 312
323 ShouldApplyAnimationType shouldApply = 313 bool shouldApply = shouldApplyAnimation(*targetElement, attributeName());
324 shouldApplyAnimation(targetElement, attributeName()); 314 if (m_animator.isAnimatingCSSProperty()) {
325 if (shouldApply == ApplyXMLandCSSAnimation ||
326 m_animator.isAnimatingCSSProperty()) {
327 // CSS properties animation code-path. 315 // CSS properties animation code-path.
328 if (shouldApply != DontApplyAnimation) { 316 if (shouldApply) {
329 CSSPropertyID id = cssPropertyID(attributeName().localName()); 317 MutableStylePropertySet* propertySet =
330 targetElement->ensureAnimatedSMILStyleProperties()->removeProperty(id); 318 targetElement->ensureAnimatedSMILStyleProperties();
331 targetElement->setNeedsStyleRecalc( 319 if (propertySet->removeProperty(m_animator.cssProperty())) {
332 LocalStyleChange, 320 targetElement->setNeedsStyleRecalc(
333 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); 321 LocalStyleChange,
322 StyleChangeReasonForTracing::create(StyleChangeReason::Animation));
323 }
334 } 324 }
335 } 325 }
336 if (shouldApply == ApplyXMLandCSSAnimation || 326 if (m_animator.isAnimatingSVGDom()) {
337 m_animator.isAnimatingSVGDom()) {
338 // SVG DOM animVal animation code-path. 327 // SVG DOM animVal animation code-path.
339 targetElement->clearAnimatedAttribute(attributeName()); 328 targetElement->clearAnimatedAttribute(attributeName());
340 if (shouldApply != DontApplyAnimation) 329 if (shouldApply)
341 targetElement->invalidateAnimatedAttribute(attributeName()); 330 targetElement->invalidateAnimatedAttribute(attributeName());
342 } 331 }
343 332
344 m_animatedProperty.clear(); 333 m_animatedProperty.clear();
345 m_animator.clear(); 334 m_animator.clear();
346 } 335 }
347 336
348 void SVGAnimateElement::applyResultsToTarget() { 337 void SVGAnimateElement::applyResultsToTarget() {
349 ASSERT(animatedPropertyType() != AnimatedTransformList || 338 ASSERT(animatedPropertyType() != AnimatedTransformList ||
350 isSVGAnimateTransformElement(*this)); 339 isSVGAnimateTransformElement(*this));
351 ASSERT(animatedPropertyType() != AnimatedUnknown); 340 ASSERT(animatedPropertyType() != AnimatedUnknown);
352 341
353 // Early exit if our animated type got destructed by a previous 342 // Early exit if our animated type got destructed by a previous
354 // endedActiveInterval(). 343 // endedActiveInterval().
355 if (!m_animatedProperty) 344 if (!m_animatedProperty)
356 return; 345 return;
357 346
347 if (!shouldApplyAnimation(*targetElement(), attributeName()))
348 return;
349
358 // We do update the style and the animation property independent of each 350 // We do update the style and the animation property independent of each
359 // other. 351 // other.
360 ShouldApplyAnimationType shouldApply = 352 if (m_animator.isAnimatingCSSProperty()) {
361 shouldApplyAnimation(targetElement(), attributeName());
362 if (shouldApply == DontApplyAnimation)
363 return;
364 if (shouldApply == ApplyXMLandCSSAnimation ||
365 m_animator.isAnimatingCSSProperty()) {
366 // CSS properties animation code-path. 353 // CSS properties animation code-path.
367 // Convert the result of the animation to a String and apply it as CSS 354 // Convert the result of the animation to a String and apply it as CSS
368 // property on the target. 355 // property on the target.
369 CSSPropertyID id = cssPropertyID(attributeName().localName());
370 MutableStylePropertySet* propertySet = 356 MutableStylePropertySet* propertySet =
371 targetElement()->ensureAnimatedSMILStyleProperties(); 357 targetElement()->ensureAnimatedSMILStyleProperties();
372 if (propertySet->setProperty(id, m_animatedProperty->valueAsString(), false, 358 if (propertySet->setProperty(m_animator.cssProperty(),
373 0)) 359 m_animatedProperty->valueAsString(), false,
360 0)) {
374 targetElement()->setNeedsStyleRecalc( 361 targetElement()->setNeedsStyleRecalc(
375 LocalStyleChange, 362 LocalStyleChange,
376 StyleChangeReasonForTracing::create(StyleChangeReason::Animation)); 363 StyleChangeReasonForTracing::create(StyleChangeReason::Animation));
364 }
377 } 365 }
378 if (shouldApply == ApplyXMLandCSSAnimation || 366 if (m_animator.isAnimatingSVGDom()) {
379 m_animator.isAnimatingSVGDom()) {
380 // SVG DOM animVal animation code-path. 367 // SVG DOM animVal animation code-path.
381 // At this point the SVG DOM values are already changed, unlike for CSS. 368 // At this point the SVG DOM values are already changed, unlike for CSS.
382 // We only have to trigger update notifications here. 369 // We only have to trigger update notifications here.
383 targetElement()->invalidateAnimatedAttribute(attributeName()); 370 targetElement()->invalidateAnimatedAttribute(attributeName());
384 } 371 }
385 } 372 }
386 373
387 bool SVGAnimateElement::animatedPropertyTypeSupportsAddition() { 374 bool SVGAnimateElement::animatedPropertyTypeSupportsAddition() {
388 // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties. 375 // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties.
389 switch (animatedPropertyType()) { 376 switch (animatedPropertyType()) {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 DEFINE_TRACE(SVGAnimateElement) { 460 DEFINE_TRACE(SVGAnimateElement) {
474 visitor->trace(m_fromProperty); 461 visitor->trace(m_fromProperty);
475 visitor->trace(m_toProperty); 462 visitor->trace(m_toProperty);
476 visitor->trace(m_toAtEndOfDurationProperty); 463 visitor->trace(m_toAtEndOfDurationProperty);
477 visitor->trace(m_animatedProperty); 464 visitor->trace(m_animatedProperty);
478 visitor->trace(m_animator); 465 visitor->trace(m_animator);
479 SVGAnimationElement::trace(visitor); 466 SVGAnimationElement::trace(visitor);
480 } 467 }
481 468
482 } // namespace blink 469 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/SVGAnimateElement.h ('k') | third_party/WebKit/Source/core/svg/SVGAnimatedTypeAnimator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698