| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/animation/StringKeyframe.h" | 6 #include "core/animation/StringKeyframe.h" |
| 7 | 7 |
| 8 #include "core/animation/AngleSVGInterpolation.h" | 8 #include "core/animation/AngleSVGInterpolation.h" |
| 9 #include "core/animation/AnimationType.h" |
| 9 #include "core/animation/ColorStyleInterpolation.h" | 10 #include "core/animation/ColorStyleInterpolation.h" |
| 10 #include "core/animation/CompositorAnimations.h" | 11 #include "core/animation/CompositorAnimations.h" |
| 11 #include "core/animation/ConstantStyleInterpolation.h" | 12 #include "core/animation/ConstantStyleInterpolation.h" |
| 13 #include "core/animation/DefaultAnimationType.h" |
| 12 #include "core/animation/DefaultSVGInterpolation.h" | 14 #include "core/animation/DefaultSVGInterpolation.h" |
| 13 #include "core/animation/DeferredLegacyStyleInterpolation.h" | 15 #include "core/animation/DeferredLegacyStyleInterpolation.h" |
| 14 #include "core/animation/DoubleStyleInterpolation.h" | 16 #include "core/animation/DoubleStyleInterpolation.h" |
| 15 #include "core/animation/FilterStyleInterpolation.h" | 17 #include "core/animation/FilterStyleInterpolation.h" |
| 16 #include "core/animation/ImageSliceStyleInterpolation.h" | 18 #include "core/animation/ImageSliceStyleInterpolation.h" |
| 17 #include "core/animation/ImageStyleInterpolation.h" | 19 #include "core/animation/ImageStyleInterpolation.h" |
| 18 #include "core/animation/IntegerOptionalIntegerSVGInterpolation.h" | 20 #include "core/animation/IntegerOptionalIntegerSVGInterpolation.h" |
| 19 #include "core/animation/IntegerSVGInterpolation.h" | 21 #include "core/animation/IntegerSVGInterpolation.h" |
| 22 #include "core/animation/InvalidatableStyleInterpolation.h" |
| 20 #include "core/animation/LegacyStyleInterpolation.h" | 23 #include "core/animation/LegacyStyleInterpolation.h" |
| 21 #include "core/animation/LengthBoxStyleInterpolation.h" | 24 #include "core/animation/LengthBoxStyleInterpolation.h" |
| 22 #include "core/animation/LengthPairStyleInterpolation.h" | 25 #include "core/animation/LengthPairStyleInterpolation.h" |
| 23 #include "core/animation/LengthSVGInterpolation.h" | 26 #include "core/animation/LengthSVGInterpolation.h" |
| 24 #include "core/animation/LengthStyleInterpolation.h" | 27 #include "core/animation/LengthStyleInterpolation.h" |
| 25 #include "core/animation/ListSVGInterpolation.h" | 28 #include "core/animation/ListSVGInterpolation.h" |
| 26 #include "core/animation/ListStyleInterpolation.h" | 29 #include "core/animation/ListStyleInterpolation.h" |
| 27 #include "core/animation/NumberOptionalNumberSVGInterpolation.h" | 30 #include "core/animation/NumberOptionalNumberSVGInterpolation.h" |
| 28 #include "core/animation/NumberSVGInterpolation.h" | 31 #include "core/animation/NumberSVGInterpolation.h" |
| 29 #include "core/animation/PathSVGInterpolation.h" | 32 #include "core/animation/PathSVGInterpolation.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 properties.add(PropertyHandle(*key)); | 84 properties.add(PropertyHandle(*key)); |
| 82 | 85 |
| 83 return properties; | 86 return properties; |
| 84 } | 87 } |
| 85 | 88 |
| 86 PassRefPtrWillBeRawPtr<Keyframe> StringKeyframe::clone() const | 89 PassRefPtrWillBeRawPtr<Keyframe> StringKeyframe::clone() const |
| 87 { | 90 { |
| 88 return adoptRefWillBeNoop(new StringKeyframe(*this)); | 91 return adoptRefWillBeNoop(new StringKeyframe(*this)); |
| 89 } | 92 } |
| 90 | 93 |
| 91 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::creat
ePropertySpecificKeyframe(PropertyHandle property) const | 94 PassRefPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::creat
ePropertySpecificKeyframe(PropertyHandle property) const |
| 92 { | 95 { |
| 93 if (property.isCSSProperty()) | 96 if (property.isCSSProperty()) |
| 94 return adoptPtrWillBeNoop(new CSSPropertySpecificKeyframe(offset(), &eas
ing(), cssPropertyValue(property.cssProperty()), composite())); | 97 return adoptRefWillBeNoop(new CSSPropertySpecificKeyframe(offset(), &eas
ing(), cssPropertyValue(property.cssProperty()), composite())); |
| 95 | 98 |
| 96 ASSERT(property.isSVGAttribute()); | 99 ASSERT(property.isSVGAttribute()); |
| 97 return adoptPtrWillBeNoop(new SVGPropertySpecificKeyframe(offset(), &easing(
), svgPropertyValue(*property.svgAttribute()), composite())); | 100 return adoptRefWillBeNoop(new SVGPropertySpecificKeyframe(offset(), &easing(
), svgPropertyValue(*property.svgAttribute()), composite())); |
| 98 } | 101 } |
| 99 | 102 |
| 100 DEFINE_TRACE(StringKeyframe) | 103 DEFINE_TRACE(StringKeyframe) |
| 101 { | 104 { |
| 102 visitor->trace(m_propertySet); | 105 visitor->trace(m_propertySet); |
| 103 Keyframe::trace(visitor); | 106 Keyframe::trace(visitor); |
| 104 } | 107 } |
| 105 | 108 |
| 106 StringKeyframe::CSSPropertySpecificKeyframe::CSSPropertySpecificKeyframe(double
offset, PassRefPtr<TimingFunction> easing, CSSValue* value, EffectModel::Composi
teOperation op) | 109 StringKeyframe::CSSPropertySpecificKeyframe::CSSPropertySpecificKeyframe(double
offset, PassRefPtr<TimingFunction> easing, CSSValue* value, EffectModel::Composi
teOperation op) |
| 107 : Keyframe::PropertySpecificKeyframe(offset, easing, op) | 110 : Keyframe::PropertySpecificKeyframe(offset, easing, op) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 case CSSPropertyStrokeMiterlimit: | 146 case CSSPropertyStrokeMiterlimit: |
| 144 return RangeGreaterThanOrEqualToOne; | 147 return RangeGreaterThanOrEqualToOne; |
| 145 case CSSPropertyFontSizeAdjust: | 148 case CSSPropertyFontSizeAdjust: |
| 146 return RangeNonNegative; | 149 return RangeNonNegative; |
| 147 default: | 150 default: |
| 148 ASSERT_NOT_REACHED(); | 151 ASSERT_NOT_REACHED(); |
| 149 return RangeAll; | 152 return RangeAll; |
| 150 } | 153 } |
| 151 } | 154 } |
| 152 | 155 |
| 156 const Vector<const AnimationType*>* applicableTypesForProperty(CSSPropertyID pro
perty) |
| 157 { |
| 158 using ApplicableTypesMap = HashMap<CSSPropertyID, const Vector<const Animati
onType*>*>; |
| 159 DEFINE_STATIC_LOCAL(ApplicableTypesMap, applicableTypesMap, ()); |
| 160 if (applicableTypesMap.contains(property)) |
| 161 return applicableTypesMap.get(property); |
| 162 |
| 163 auto applicableTypes = new Vector<const AnimationType*>(); |
| 164 // TODO(alancutter): Add sufficient data to CSSProperties.in to auto generat
e this switch statement. |
| 165 // TODO(alancutter): Support all animatable CSS properties here so we can st
op falling back to the old StyleInterpolation implementation. |
| 166 switch (property) { |
| 167 default: |
| 168 if (!CSSPropertyMetadata::isAnimatableProperty(property)) |
| 169 break; |
| 170 delete(applicableTypes); |
| 171 return nullptr; |
| 172 } |
| 173 applicableTypes->append(new DefaultAnimationType(property)); |
| 174 applicableTypesMap.add(property, applicableTypes); |
| 175 return applicableTypes; |
| 176 } |
| 177 |
| 153 } // namespace | 178 } // namespace |
| 154 | 179 |
| 155 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::CSSPropertySpecificKeyfram
e::maybeCreateInterpolation(PropertyHandle propertyHandle, Keyframe::PropertySpe
cificKeyframe& end, Element* element, const ComputedStyle* baseStyle) const | 180 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::CSSPropertySpecificKeyfram
e::maybeCreateInterpolation(PropertyHandle propertyHandle, Keyframe::PropertySpe
cificKeyframe& end, Element* element, const ComputedStyle* baseStyle) |
| 156 { | 181 { |
| 157 CSSPropertyID property = propertyHandle.cssProperty(); | 182 CSSPropertyID property = propertyHandle.cssProperty(); |
| 183 const Vector<const AnimationType*>* applicableTypes = applicableTypesForProp
erty(property); |
| 184 if (applicableTypes) |
| 185 return InvalidatableStyleInterpolation::create(*applicableTypes, this, t
oCSSPropertySpecificKeyframe(&end)); |
| 186 |
| 187 // TODO(alancutter): Remove the remainder of this function. |
| 158 | 188 |
| 159 // FIXME: Refactor this into a generic piece that lives in InterpolationEffe
ct, and a template parameter specific converter. | 189 // FIXME: Refactor this into a generic piece that lives in InterpolationEffe
ct, and a template parameter specific converter. |
| 160 CSSValue* fromCSSValue = m_value.get(); | 190 CSSValue* fromCSSValue = m_value.get(); |
| 161 CSSValue* toCSSValue = toCSSPropertySpecificKeyframe(end).value(); | 191 CSSValue* toCSSValue = toCSSPropertySpecificKeyframe(end).value(); |
| 162 InterpolationRange range = RangeAll; | 192 InterpolationRange range = RangeAll; |
| 163 bool fallBackToLegacy = false; | 193 bool fallBackToLegacy = false; |
| 164 | 194 |
| 165 // FIXME: Remove this flag once we can rely on legacy's behaviour being corr
ect. | 195 // FIXME: Remove this flag once we can rely on legacy's behaviour being corr
ect. |
| 166 bool forceDefaultInterpolation = false; | 196 bool forceDefaultInterpolation = false; |
| 167 | 197 |
| 168 // FIXME: Remove this check once neutral keyframes are implemented in String
Keyframes. | 198 // FIXME: Remove this check once neutral keyframes are implemented in String
Keyframes. |
| 169 if (!fromCSSValue || !toCSSValue) | 199 if (!fromCSSValue || !toCSSValue) |
| 170 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSValue
, property); | 200 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSValue
, property); |
| 171 | 201 |
| 172 ASSERT(fromCSSValue && toCSSValue); | 202 ASSERT(fromCSSValue && toCSSValue); |
| 173 | 203 |
| 174 if (!CSSPropertyMetadata::isAnimatableProperty(property)) { | 204 if (!CSSPropertyMetadata::isAnimatableProperty(property)) { |
| 175 if (fromCSSValue == toCSSValue) | 205 if (fromCSSValue == toCSSValue) |
| 176 return ConstantStyleInterpolation::create(fromCSSValue, property); | 206 return ConstantStyleInterpolation::create(fromCSSValue, property); |
| 177 | 207 |
| 178 return nullptr; | 208 return nullptr; |
| 179 } | 209 } |
| 180 | 210 |
| 181 // FIXME: Generate this giant switch statement. | |
| 182 switch (property) { | 211 switch (property) { |
| 183 case CSSPropertyLineHeight: | 212 case CSSPropertyLineHeight: |
| 184 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) | 213 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyl
eInterpolation::canCreateFrom(*toCSSValue)) |
| 185 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, RangeNonNegative); | 214 return LengthStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, RangeNonNegative); |
| 186 | 215 |
| 187 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) | 216 if (DoubleStyleInterpolation::canCreateFrom(*fromCSSValue) && DoubleStyl
eInterpolation::canCreateFrom(*toCSSValue)) |
| 188 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, CSSPrimitiveValue::CSS_NUMBER, RangeNonNegative); | 217 return DoubleStyleInterpolation::create(*fromCSSValue, *toCSSValue,
property, CSSPrimitiveValue::CSS_NUMBER, RangeNonNegative); |
| 189 | 218 |
| 190 break; | 219 break; |
| 191 case CSSPropertyBorderBottomWidth: | 220 case CSSPropertyBorderBottomWidth: |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 } | 460 } |
| 432 | 461 |
| 433 ASSERT(AnimatableValue::usesDefaultInterpolation( | 462 ASSERT(AnimatableValue::usesDefaultInterpolation( |
| 434 StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, proper
ty, fromCSSValue).get(), | 463 StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, proper
ty, fromCSSValue).get(), |
| 435 StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, proper
ty, toCSSValue).get())); | 464 StyleResolver::createAnimatableValueSnapshot(*element, baseStyle, proper
ty, toCSSValue).get())); |
| 436 | 465 |
| 437 return nullptr; | 466 return nullptr; |
| 438 | 467 |
| 439 } | 468 } |
| 440 | 469 |
| 441 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::CSSPr
opertySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction
> easing) const | 470 PassRefPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::CSSPr
opertySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction
> easing) const |
| 442 { | 471 { |
| 443 return adoptPtrWillBeNoop(new CSSPropertySpecificKeyframe(offset, easing, st
atic_cast<CSSValue*>(0), EffectModel::CompositeAdd)); | 472 return adoptRefWillBeNoop(new CSSPropertySpecificKeyframe(offset, easing, st
atic_cast<CSSValue*>(0), EffectModel::CompositeAdd)); |
| 444 } | 473 } |
| 445 | 474 |
| 446 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::CSSPr
opertySpecificKeyframe::cloneWithOffset(double offset) const | 475 PassRefPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::CSSPr
opertySpecificKeyframe::cloneWithOffset(double offset) const |
| 447 { | 476 { |
| 448 Keyframe::PropertySpecificKeyframe* theClone = new CSSPropertySpecificKeyfra
me(offset, m_easing, m_value.get()); | 477 Keyframe::PropertySpecificKeyframe* theClone = new CSSPropertySpecificKeyfra
me(offset, m_easing, m_value.get()); |
| 449 toCSSPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_animatab
leValueCache; | 478 toCSSPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_animatab
leValueCache; |
| 450 return adoptPtrWillBeNoop(theClone); | 479 return adoptRefWillBeNoop(theClone); |
| 451 } | 480 } |
| 452 | 481 |
| 453 DEFINE_TRACE(StringKeyframe::CSSPropertySpecificKeyframe) | 482 DEFINE_TRACE(StringKeyframe::CSSPropertySpecificKeyframe) |
| 454 { | 483 { |
| 455 visitor->trace(m_value); | 484 visitor->trace(m_value); |
| 456 visitor->trace(m_animatableValueCache); | 485 visitor->trace(m_animatableValueCache); |
| 457 Keyframe::PropertySpecificKeyframe::trace(visitor); | 486 Keyframe::PropertySpecificKeyframe::trace(visitor); |
| 458 } | 487 } |
| 459 | 488 |
| 460 SVGPropertySpecificKeyframe::SVGPropertySpecificKeyframe(double offset, PassRefP
tr<TimingFunction> easing, const String& value, EffectModel::CompositeOperation
op) | 489 SVGPropertySpecificKeyframe::SVGPropertySpecificKeyframe(double offset, PassRefP
tr<TimingFunction> easing, const String& value, EffectModel::CompositeOperation
op) |
| 461 : Keyframe::PropertySpecificKeyframe(offset, easing, op) | 490 : Keyframe::PropertySpecificKeyframe(offset, easing, op) |
| 462 , m_value(value) | 491 , m_value(value) |
| 463 { | 492 { |
| 464 } | 493 } |
| 465 | 494 |
| 466 SVGPropertySpecificKeyframe::SVGPropertySpecificKeyframe(double offset, PassRefP
tr<TimingFunction> easing, const String& value) | 495 SVGPropertySpecificKeyframe::SVGPropertySpecificKeyframe(double offset, PassRefP
tr<TimingFunction> easing, const String& value) |
| 467 : Keyframe::PropertySpecificKeyframe(offset, easing, EffectModel::CompositeR
eplace) | 496 : Keyframe::PropertySpecificKeyframe(offset, easing, EffectModel::CompositeR
eplace) |
| 468 , m_value(value) | 497 , m_value(value) |
| 469 { | 498 { |
| 470 ASSERT(!isNull(m_offset)); | 499 ASSERT(!isNull(m_offset)); |
| 471 } | 500 } |
| 472 | 501 |
| 473 DEFINE_TRACE(StringKeyframe::SVGPropertySpecificKeyframe) | 502 DEFINE_TRACE(StringKeyframe::SVGPropertySpecificKeyframe) |
| 474 { | 503 { |
| 475 Keyframe::PropertySpecificKeyframe::trace(visitor); | 504 Keyframe::PropertySpecificKeyframe::trace(visitor); |
| 476 } | 505 } |
| 477 | 506 |
| 478 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> SVGPropertySpecificKe
yframe::cloneWithOffset(double offset) const | 507 PassRefPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> SVGPropertySpecificKe
yframe::cloneWithOffset(double offset) const |
| 479 { | 508 { |
| 480 return adoptPtrWillBeNoop(new SVGPropertySpecificKeyframe(offset, m_easing,
m_value)); | 509 return adoptRefWillBeNoop(new SVGPropertySpecificKeyframe(offset, m_easing,
m_value)); |
| 481 } | 510 } |
| 482 | 511 |
| 483 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> SVGPropertySpecificKe
yframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const | 512 PassRefPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> SVGPropertySpecificKe
yframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const |
| 484 { | 513 { |
| 485 return adoptPtrWillBeNoop(new SVGPropertySpecificKeyframe(offset, easing, ""
, EffectModel::CompositeAdd)); | 514 return adoptRefWillBeNoop(new SVGPropertySpecificKeyframe(offset, easing, ""
, EffectModel::CompositeAdd)); |
| 486 } | 515 } |
| 487 | 516 |
| 488 namespace { | 517 namespace { |
| 489 | 518 |
| 490 PassRefPtrWillBeRawPtr<Interpolation> createSVGInterpolation(SVGPropertyBase* fr
omValue, SVGPropertyBase* toValue, SVGAnimatedPropertyBase* attribute) | 519 PassRefPtrWillBeRawPtr<Interpolation> createSVGInterpolation(SVGPropertyBase* fr
omValue, SVGPropertyBase* toValue, SVGAnimatedPropertyBase* attribute) |
| 491 { | 520 { |
| 492 RefPtrWillBeRawPtr<Interpolation> interpolation = nullptr; | 521 RefPtrWillBeRawPtr<Interpolation> interpolation = nullptr; |
| 493 ASSERT(fromValue->type() == toValue->type()); | 522 ASSERT(fromValue->type() == toValue->type()); |
| 494 switch (fromValue->type()) { | 523 switch (fromValue->type()) { |
| 495 case AnimatedAngle: | 524 case AnimatedAngle: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 533 break; | 562 break; |
| 534 } | 563 } |
| 535 if (interpolation) | 564 if (interpolation) |
| 536 return interpolation.release(); | 565 return interpolation.release(); |
| 537 | 566 |
| 538 return DefaultSVGInterpolation::create(fromValue, toValue, attribute); | 567 return DefaultSVGInterpolation::create(fromValue, toValue, attribute); |
| 539 } | 568 } |
| 540 | 569 |
| 541 } // namespace | 570 } // namespace |
| 542 | 571 |
| 543 PassRefPtrWillBeRawPtr<Interpolation> SVGPropertySpecificKeyframe::maybeCreateIn
terpolation(PropertyHandle propertyHandle, Keyframe::PropertySpecificKeyframe& e
nd, Element* element, const ComputedStyle* baseStyle) const | 572 PassRefPtrWillBeRawPtr<Interpolation> SVGPropertySpecificKeyframe::maybeCreateIn
terpolation(PropertyHandle propertyHandle, Keyframe::PropertySpecificKeyframe& e
nd, Element* element, const ComputedStyle* baseStyle) |
| 544 { | 573 { |
| 545 ASSERT(element); | 574 ASSERT(element); |
| 546 RefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute = toSVGElement(element
)->propertyFromAttribute(*propertyHandle.svgAttribute()); | 575 RefPtrWillBeRawPtr<SVGAnimatedPropertyBase> attribute = toSVGElement(element
)->propertyFromAttribute(*propertyHandle.svgAttribute()); |
| 547 ASSERT(attribute); | 576 ASSERT(attribute); |
| 548 | 577 |
| 549 RefPtrWillBeRawPtr<SVGPropertyBase> fromValue = attribute->currentValueBase(
)->cloneForAnimation(m_value); | 578 RefPtrWillBeRawPtr<SVGPropertyBase> fromValue = attribute->currentValueBase(
)->cloneForAnimation(m_value); |
| 550 RefPtrWillBeRawPtr<SVGPropertyBase> toValue = attribute->currentValueBase()-
>cloneForAnimation(toSVGPropertySpecificKeyframe(end).value()); | 579 RefPtrWillBeRawPtr<SVGPropertyBase> toValue = attribute->currentValueBase()-
>cloneForAnimation(toSVGPropertySpecificKeyframe(end).value()); |
| 551 | 580 |
| 552 if (!fromValue || !toValue) | 581 if (!fromValue || !toValue) |
| 553 return nullptr; | 582 return nullptr; |
| 554 | 583 |
| 555 return createSVGInterpolation(fromValue.get(), toValue.get(), attribute.get(
)); | 584 return createSVGInterpolation(fromValue.get(), toValue.get(), attribute.get(
)); |
| 556 } | 585 } |
| 557 | 586 |
| 558 } // namespace blink | 587 } // namespace blink |
| OLD | NEW |