| Index: third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
|
| diff --git a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
|
| index 67e710b6f227f0a0e333521b3583384e95d910cb..ee425ba764a2deff0e630de1dccfb53d2b05cb4f 100644
|
| --- a/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
|
| +++ b/third_party/WebKit/Source/core/svg/SVGAnimateElement.cpp
|
| @@ -27,6 +27,12 @@
|
| #include "core/dom/Document.h"
|
| #include "core/dom/QualifiedName.h"
|
| #include "core/dom/StyleChangeReason.h"
|
| +#include "core/svg/SVGAnimatedColor.h"
|
| +#include "core/svg/SVGLength.h"
|
| +#include "core/svg/SVGLengthList.h"
|
| +#include "core/svg/SVGNumber.h"
|
| +#include "core/svg/SVGString.h"
|
| +#include "core/svg/properties/SVGAnimatedProperty.h"
|
| #include "core/svg/properties/SVGProperty.h"
|
|
|
| namespace blink {
|
| @@ -68,7 +74,8 @@ AnimatedPropertyValueType propertyValueType(const QualifiedName& attributeName,
|
| SVGAnimateElement::SVGAnimateElement(const QualifiedName& tagName,
|
| Document& document)
|
| : SVGAnimationElement(tagName, document),
|
| - m_animator(this),
|
| + m_type(AnimatedUnknown),
|
| + m_cssPropertyId(CSSPropertyInvalid),
|
| m_fromPropertyValueType(RegularPropertyValue),
|
| m_toPropertyValueType(RegularPropertyValue),
|
| m_attributeType(AttributeTypeAuto),
|
| @@ -120,12 +127,40 @@ void SVGAnimateElement::svgAttributeChanged(const QualifiedName& attrName) {
|
| SVGAnimationElement::svgAttributeChanged(attrName);
|
| }
|
|
|
| +void SVGAnimateElement::resolveTargetProperty() {
|
| + DCHECK(targetElement());
|
| + m_targetProperty = targetElement()->propertyFromAttribute(attributeName());
|
| + if (m_targetProperty) {
|
| + m_type = m_targetProperty->type();
|
| + m_cssPropertyId = m_targetProperty->cssPropertyId();
|
| +
|
| + // Only <animateTransform> is allowed to animate AnimatedTransformList.
|
| + // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties
|
| + if (m_type == AnimatedTransformList) {
|
| + m_type = AnimatedUnknown;
|
| + m_cssPropertyId = CSSPropertyInvalid;
|
| + }
|
| + } else {
|
| + m_type = SVGElement::animatedPropertyTypeForCSSAttribute(attributeName());
|
| + m_cssPropertyId = m_type != AnimatedUnknown
|
| + ? cssPropertyID(attributeName().localName())
|
| + : CSSPropertyInvalid;
|
| + }
|
| + DCHECK(m_type != AnimatedPoint && m_type != AnimatedStringList &&
|
| + m_type != AnimatedTransform && m_type != AnimatedTransformList);
|
| +}
|
| +
|
| +void SVGAnimateElement::clearTargetProperty() {
|
| + m_targetProperty = nullptr;
|
| + m_type = AnimatedUnknown;
|
| + m_cssPropertyId = CSSPropertyInvalid;
|
| +}
|
| +
|
| AnimatedPropertyType SVGAnimateElement::animatedPropertyType() {
|
| if (!targetElement())
|
| return AnimatedUnknown;
|
| -
|
| - m_animator.reset(*targetElement());
|
| - return m_animator.type();
|
| + resolveTargetProperty();
|
| + return m_type;
|
| }
|
|
|
| bool SVGAnimateElement::hasValidTarget() {
|
| @@ -160,6 +195,81 @@ bool SVGAnimateElement::shouldApplyAnimation(
|
| return getAttributeType() != AttributeTypeCSS;
|
| }
|
|
|
| +SVGPropertyBase* SVGAnimateElement::createPropertyForAttributeAnimation(
|
| + const String& value) const {
|
| + // SVG DOM animVal animation code-path.
|
| + // TransformList must be animated via <animateTransform>, and its
|
| + // {from,by,to} attribute values needs to be parsed w.r.t. its "type"
|
| + // attribute. Spec:
|
| + // http://www.w3.org/TR/SVG/single-page.html#animate-AnimateTransformElement
|
| + DCHECK_NE(m_type, AnimatedTransformList);
|
| + DCHECK(m_targetProperty);
|
| + return m_targetProperty->currentValueBase()->cloneForAnimation(value);
|
| +}
|
| +
|
| +SVGPropertyBase* SVGAnimateElement::createPropertyForCSSAnimation(
|
| + const String& value) const {
|
| + // CSS properties animation code-path.
|
| + // Create a basic instance of the corresponding SVG property.
|
| + // The instance will not have full context info. (e.g. SVGLengthMode)
|
| + switch (m_type) {
|
| + case AnimatedColor:
|
| + return SVGColorProperty::create(value);
|
| + case AnimatedNumber: {
|
| + SVGNumber* property = SVGNumber::create();
|
| + property->setValueAsString(value);
|
| + return property;
|
| + }
|
| + case AnimatedLength: {
|
| + SVGLength* property = SVGLength::create();
|
| + property->setValueAsString(value);
|
| + return property;
|
| + }
|
| + case AnimatedLengthList: {
|
| + SVGLengthList* property = SVGLengthList::create();
|
| + property->setValueAsString(value);
|
| + return property;
|
| + }
|
| + case AnimatedString: {
|
| + SVGString* property = SVGString::create();
|
| + property->setValueAsString(value);
|
| + return property;
|
| + }
|
| + // These types don't appear in the table in
|
| + // SVGElement::animatedPropertyTypeForCSSAttribute() and thus don't need
|
| + // support.
|
| + case AnimatedAngle:
|
| + case AnimatedBoolean:
|
| + case AnimatedEnumeration:
|
| + case AnimatedInteger:
|
| + case AnimatedIntegerOptionalInteger:
|
| + case AnimatedNumberList:
|
| + case AnimatedNumberOptionalNumber:
|
| + case AnimatedPath:
|
| + case AnimatedPoint:
|
| + case AnimatedPoints:
|
| + case AnimatedPreserveAspectRatio:
|
| + case AnimatedRect:
|
| + case AnimatedStringList:
|
| + case AnimatedTransform:
|
| + case AnimatedTransformList:
|
| + case AnimatedUnknown:
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + NOTREACHED();
|
| + return nullptr;
|
| +}
|
| +
|
| +SVGPropertyBase* SVGAnimateElement::createPropertyForAnimation(
|
| + const String& value) const {
|
| + if (isAnimatingSVGDom())
|
| + return createPropertyForAttributeAnimation(value);
|
| + DCHECK(isAnimatingCSSProperty());
|
| + return createPropertyForCSSAnimation(value);
|
| +}
|
| +
|
| SVGPropertyBase* SVGAnimateElement::adjustForInheritance(
|
| SVGPropertyBase* propertyValue,
|
| AnimatedPropertyValueType valueType) const {
|
| @@ -174,8 +284,8 @@ SVGPropertyBase* SVGAnimateElement::adjustForInheritance(
|
| return propertyValue;
|
| SVGElement* svgParent = toSVGElement(parent);
|
| // Replace 'inherit' by its computed property value.
|
| - String value = computeCSSPropertyValue(svgParent, m_animator.cssProperty());
|
| - return m_animator.createPropertyForAnimation(value);
|
| + String value = computeCSSPropertyValue(svgParent, m_cssPropertyId);
|
| + return createPropertyForAnimation(value);
|
| }
|
|
|
| void SVGAnimateElement::calculateAnimatedValue(float percentage,
|
| @@ -186,19 +296,17 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage,
|
| if (!isSVGAnimateElement(*resultElement))
|
| return;
|
|
|
| - ASSERT(percentage >= 0 && percentage <= 1);
|
| - ASSERT(animatedPropertyType() != AnimatedTransformList ||
|
| - isSVGAnimateTransformElement(*this));
|
| - ASSERT(animatedPropertyType() != AnimatedUnknown);
|
| - ASSERT(m_fromProperty);
|
| - ASSERT(m_fromProperty->type() == animatedPropertyType());
|
| - ASSERT(m_toProperty);
|
| + DCHECK(percentage >= 0 && percentage <= 1);
|
| + DCHECK_NE(animatedPropertyType(), AnimatedUnknown);
|
| + DCHECK(m_fromProperty);
|
| + DCHECK_EQ(m_fromProperty->type(), animatedPropertyType());
|
| + DCHECK(m_toProperty);
|
|
|
| SVGAnimateElement* resultAnimationElement =
|
| toSVGAnimateElement(resultElement);
|
| - ASSERT(resultAnimationElement->m_animatedProperty);
|
| - ASSERT(resultAnimationElement->animatedPropertyType() ==
|
| - animatedPropertyType());
|
| + DCHECK(resultAnimationElement->m_animatedValue);
|
| + DCHECK_EQ(resultAnimationElement->animatedPropertyType(),
|
| + animatedPropertyType());
|
|
|
| if (isSVGSetElement(*this))
|
| percentage = 1;
|
| @@ -211,7 +319,7 @@ void SVGAnimateElement::calculateAnimatedValue(float percentage,
|
|
|
| // Values-animation accumulates using the last values entry corresponding to
|
| // the end of duration time.
|
| - SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedProperty;
|
| + SVGPropertyBase* animatedValue = resultAnimationElement->m_animatedValue;
|
| SVGPropertyBase* toAtEndOfDurationValue =
|
| m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty : m_toProperty;
|
| SVGPropertyBase* fromValue =
|
| @@ -232,16 +340,16 @@ bool SVGAnimateElement::calculateToAtEndOfDurationValue(
|
| if (toAtEndOfDurationString.isEmpty())
|
| return false;
|
| m_toAtEndOfDurationProperty =
|
| - m_animator.createPropertyForAnimation(toAtEndOfDurationString);
|
| + createPropertyForAnimation(toAtEndOfDurationString);
|
| return true;
|
| }
|
|
|
| bool SVGAnimateElement::calculateFromAndToValues(const String& fromString,
|
| const String& toString) {
|
| DCHECK(targetElement());
|
| - m_fromProperty = m_animator.createPropertyForAnimation(fromString);
|
| + m_fromProperty = createPropertyForAnimation(fromString);
|
| m_fromPropertyValueType = propertyValueType(attributeName(), fromString);
|
| - m_toProperty = m_animator.createPropertyForAnimation(toString);
|
| + m_toProperty = createPropertyForAnimation(toString);
|
| m_toPropertyValueType = propertyValueType(attributeName(), toString);
|
| return true;
|
| }
|
| @@ -261,41 +369,41 @@ bool SVGAnimateElement::calculateFromAndByValues(const String& fromString,
|
|
|
| DCHECK(!isSVGSetElement(*this));
|
|
|
| - m_fromProperty = m_animator.createPropertyForAnimation(fromString);
|
| + m_fromProperty = createPropertyForAnimation(fromString);
|
| m_fromPropertyValueType = propertyValueType(attributeName(), fromString);
|
| - m_toProperty = m_animator.createPropertyForAnimation(byString);
|
| + m_toProperty = createPropertyForAnimation(byString);
|
| m_toPropertyValueType = propertyValueType(attributeName(), byString);
|
| m_toProperty->add(m_fromProperty, targetElement());
|
| return true;
|
| }
|
|
|
| void SVGAnimateElement::resetAnimatedType() {
|
| + resolveTargetProperty();
|
| +
|
| SVGElement* targetElement = this->targetElement();
|
| const QualifiedName& attributeName = this->attributeName();
|
|
|
| - m_animator.reset(*targetElement);
|
| -
|
| if (!shouldApplyAnimation(*targetElement, attributeName))
|
| return;
|
| - if (m_animator.isAnimatingSVGDom()) {
|
| + if (isAnimatingSVGDom()) {
|
| // SVG DOM animVal animation code-path.
|
| - m_animatedProperty = m_animator.createAnimatedValue();
|
| - targetElement->setAnimatedAttribute(attributeName, m_animatedProperty);
|
| + m_animatedValue = m_targetProperty->createAnimatedValue();
|
| + DCHECK_EQ(m_animatedValue->type(), m_type);
|
| + targetElement->setAnimatedAttribute(attributeName, m_animatedValue);
|
| return;
|
| }
|
| - DCHECK(m_animator.isAnimatingCSSProperty());
|
| + DCHECK(isAnimatingCSSProperty());
|
| // Presentation attributes which has an SVG DOM representation should use the
|
| // "SVG DOM" code-path (above.)
|
| DCHECK(SVGElement::isAnimatableCSSProperty(attributeName));
|
|
|
| // CSS properties animation code-path.
|
| - String baseValue =
|
| - computeCSSPropertyValue(targetElement, m_animator.cssProperty());
|
| - m_animatedProperty = m_animator.createPropertyForAnimation(baseValue);
|
| + String baseValue = computeCSSPropertyValue(targetElement, m_cssPropertyId);
|
| + m_animatedValue = createPropertyForAnimation(baseValue);
|
| }
|
|
|
| void SVGAnimateElement::clearAnimatedType() {
|
| - if (!m_animatedProperty)
|
| + if (!m_animatedValue)
|
| return;
|
|
|
| // The animated property lock is held for the "result animation" (see
|
| @@ -306,42 +414,40 @@ void SVGAnimateElement::clearAnimatedType() {
|
|
|
| SVGElement* targetElement = this->targetElement();
|
| if (!targetElement) {
|
| - m_animatedProperty.clear();
|
| + m_animatedValue.clear();
|
| return;
|
| }
|
|
|
| bool shouldApply = shouldApplyAnimation(*targetElement, attributeName());
|
| - if (m_animator.isAnimatingCSSProperty()) {
|
| + if (isAnimatingCSSProperty()) {
|
| // CSS properties animation code-path.
|
| if (shouldApply) {
|
| MutableStylePropertySet* propertySet =
|
| targetElement->ensureAnimatedSMILStyleProperties();
|
| - if (propertySet->removeProperty(m_animator.cssProperty())) {
|
| + if (propertySet->removeProperty(m_cssPropertyId)) {
|
| targetElement->setNeedsStyleRecalc(
|
| LocalStyleChange,
|
| StyleChangeReasonForTracing::create(StyleChangeReason::Animation));
|
| }
|
| }
|
| }
|
| - if (m_animator.isAnimatingSVGDom()) {
|
| + if (isAnimatingSVGDom()) {
|
| // SVG DOM animVal animation code-path.
|
| targetElement->clearAnimatedAttribute(attributeName());
|
| if (shouldApply)
|
| targetElement->invalidateAnimatedAttribute(attributeName());
|
| }
|
|
|
| - m_animatedProperty.clear();
|
| - m_animator.clear();
|
| + m_animatedValue.clear();
|
| + clearTargetProperty();
|
| }
|
|
|
| void SVGAnimateElement::applyResultsToTarget() {
|
| - ASSERT(animatedPropertyType() != AnimatedTransformList ||
|
| - isSVGAnimateTransformElement(*this));
|
| - ASSERT(animatedPropertyType() != AnimatedUnknown);
|
| + DCHECK_NE(animatedPropertyType(), AnimatedUnknown);
|
|
|
| // Early exit if our animated type got destructed by a previous
|
| // endedActiveInterval().
|
| - if (!m_animatedProperty)
|
| + if (!m_animatedValue)
|
| return;
|
|
|
| if (!shouldApplyAnimation(*targetElement(), attributeName()))
|
| @@ -349,22 +455,22 @@ void SVGAnimateElement::applyResultsToTarget() {
|
|
|
| // We do update the style and the animation property independent of each
|
| // other.
|
| - if (m_animator.isAnimatingCSSProperty()) {
|
| + if (isAnimatingCSSProperty()) {
|
| // CSS properties animation code-path.
|
| // Convert the result of the animation to a String and apply it as CSS
|
| // property on the target.
|
| MutableStylePropertySet* propertySet =
|
| targetElement()->ensureAnimatedSMILStyleProperties();
|
| if (propertySet
|
| - ->setProperty(m_animator.cssProperty(),
|
| - m_animatedProperty->valueAsString(), false, 0)
|
| + ->setProperty(m_cssPropertyId, m_animatedValue->valueAsString(),
|
| + false, 0)
|
| .didChange) {
|
| targetElement()->setNeedsStyleRecalc(
|
| LocalStyleChange,
|
| StyleChangeReasonForTracing::create(StyleChangeReason::Animation));
|
| }
|
| }
|
| - if (m_animator.isAnimatingSVGDom()) {
|
| + if (isAnimatingSVGDom()) {
|
| // SVG DOM animVal animation code-path.
|
| // At this point the SVG DOM values are already changed, unlike for CSS.
|
| // We only have to trigger update notifications here.
|
| @@ -401,9 +507,8 @@ float SVGAnimateElement::calculateDistance(const String& fromString,
|
| DCHECK(targetElement());
|
| // FIXME: A return value of float is not enough to support paced animations on
|
| // lists.
|
| - SVGPropertyBase* fromValue =
|
| - m_animator.createPropertyForAnimation(fromString);
|
| - SVGPropertyBase* toValue = m_animator.createPropertyForAnimation(toString);
|
| + SVGPropertyBase* fromValue = createPropertyForAnimation(fromString);
|
| + SVGPropertyBase* toValue = createPropertyForAnimation(toString);
|
| return fromValue->calculateDistance(toValue, targetElement());
|
| }
|
|
|
| @@ -451,19 +556,19 @@ void SVGAnimateElement::checkInvalidCSSAttributeType() {
|
| }
|
|
|
| void SVGAnimateElement::resetAnimatedPropertyType() {
|
| - ASSERT(!m_animatedProperty);
|
| + DCHECK(!m_animatedValue);
|
| m_fromProperty.clear();
|
| m_toProperty.clear();
|
| m_toAtEndOfDurationProperty.clear();
|
| - m_animator.clear();
|
| + clearTargetProperty();
|
| }
|
|
|
| DEFINE_TRACE(SVGAnimateElement) {
|
| visitor->trace(m_fromProperty);
|
| visitor->trace(m_toProperty);
|
| visitor->trace(m_toAtEndOfDurationProperty);
|
| - visitor->trace(m_animatedProperty);
|
| - visitor->trace(m_animator);
|
| + visitor->trace(m_animatedValue);
|
| + visitor->trace(m_targetProperty);
|
| SVGAnimationElement::trace(visitor);
|
| }
|
|
|
|
|