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 3 // found in the LICENSE file. 4 5 #include "config.h" 6 #include "core/animation/StringKeyframe.h" 7 8 #include "core/animation/DefaultStyleInterpolation.h" 9 #include "core/animation/DeferredLegacyStyleInterpolation.h" 10 #include "core/animation/LegacyStyleInterpolation.h" 11 #include "core/animation/LengthStyleInterpolation.h" 12 #include "core/animation/css/CSSAnimations.h" 13 #include "core/css/CSSPropertyMetadata.h" 14 #include "core/css/resolver/StyleResolver.h" 15 #include "core/rendering/style/RenderStyle.h" 16 17 namespace blink { 18 19 StringKeyframe::StringKeyframe(const StringKeyframe& copyFrom) 20 : Keyframe(copyFrom.m_offset, copyFrom.m_composite, copyFrom.m_easing) 21 , m_propertySet(copyFrom.m_propertySet->mutableCopy()) 22 { 23 } 24 25 void StringKeyframe::setPropertyValue(CSSPropertyID property, const String& value, StyleSheetContents* styleSheetContents) 26 { 27 ASSERT(property != CSSPropertyInvalid); 28 if (CSSAnimations::isAllowedAnimation(property)) 29 m_propertySet->setProperty(property, value, false, styleSheetContents); 30 } 31 32 PropertySet StringKeyframe::properties() const 33 { 34 // This is not used in time-critical code, so we probably don't need to 35 // worry about caching this result. 36 PropertySet properties; 37 for (unsigned i = 0; i < m_propertySet->propertyCount(); ++i) 38 properties.add(m_propertySet->propertyAt(i).id()); 39 return properties; 40 } 41 42 PassRefPtrWillBeRawPtr<Keyframe> StringKeyframe::clone() const 43 { 44 return adoptRefWillBeNoop(new StringKeyframe(*this)); 45 } 46 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::createPropertySpecificKeyframe(CSSPropertyID property) const 47 { 48 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset(), &easing(), propertyValue(property), composite())); 49 } 50 51 void StringKeyframe::trace(Visitor* visitor) 52 { 53 visitor->trace(m_propertySet); 54 Keyframe::trace(visitor); 55 } 56 57 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, CSSValue* value, AnimationEffect::CompositeOperation op) 58 : Keyframe::PropertySpecificKeyframe(offset, easing, op) 59 , m_value(value) 60 { } 61 62 StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, CSSValue* value) 63 : Keyframe::PropertySpecificKeyframe(offset, easing, AnimationEffect::CompositeReplace) 64 , m_value(value) 65 { 66 ASSERT(!isNull(m_offset)); 67 } 68 69 PassRefPtrWillBeRawPtr<Interpolation> StringKeyframe::PropertySpecificKeyframe::createInterpolation(CSSPropertyID property, Keyframe::PropertySpecificKeyframe* end, Element* element) const 70 { 71 CSSValue* fromCSSValue = m_value.get(); 72 CSSValue* toCSSValue = toStringPropertySpecificKeyframe(end)->value(); 73 ValueRange range = ValueRangeAll; 74 75 if (!CSSPropertyMetadata::isAnimatableProperty(property)) 76 return DefaultStyleInterpolation::create(fromCSSValue, toCSSValue, property); 77 78 switch (property) { 79 case CSSPropertyBorderBottomWidth: 80 case CSSPropertyBorderLeftWidth: 81 case CSSPropertyBorderRightWidth: 82 case CSSPropertyBorderTopWidth: 83 case CSSPropertyFontSize: 84 case CSSPropertyHeight: 85 case CSSPropertyLineHeight: 86 case CSSPropertyMaxHeight: 87 case CSSPropertyMaxWidth: 88 case CSSPropertyMinHeight: 89 case CSSPropertyMinWidth: 90 case CSSPropertyOutlineWidth: 91 case CSSPropertyPaddingBottom: 92 case CSSPropertyPaddingLeft: 93 case CSSPropertyPaddingRight: 94 case CSSPropertyPaddingTop: 95 case CSSPropertyPerspective: 96 case CSSPropertyShapeMargin: 97 case CSSPropertyWidth: 98 range = ValueRangeNonNegative; 99 // Fall through 100 case CSSPropertyBottom: 101 case CSSPropertyLeft: 102 case CSSPropertyLetterSpacing: 103 case CSSPropertyMarginBottom: 104 case CSSPropertyMarginLeft: 105 case CSSPropertyMarginRight: 106 case CSSPropertyMarginTop: 107 case CSSPropertyOutlineOffset: 108 case CSSPropertyRight: 109 case CSSPropertyTop: 110 case CSSPropertyVerticalAlign: 111 case CSSPropertyWordSpacing: 112 if (LengthStyleInterpolation::canCreateFrom(*fromCSSValue) && LengthStyleInterpolation::canCreateFrom(*toCSSValue)) 113 return LengthStyleInterpolation::create(fromCSSValue, toCSSValue, property, range); 114 break; 115 default: 116 break; 117 } 118 119 if (DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(*fromCSSValue) || DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(*toCSSValue)) 120 return DeferredLegacyStyleInterpolation::create(fromCSSValue, toCSSValue, property); 121 122 // FIXME: Remove the use of AnimatableValues, RenderStyles and Elements here. 123 // FIXME: Remove this cache 124 ASSERT(element); 125 if (!m_animatableValueCache) 126 m_animatableValueCache = StyleResolver::createAnimatableValueSnapshot(*element, property, *fromCSSValue); 127 128 RefPtrWillBeRawPtr<AnimatableValue> to = StyleResolver::createAnimatableValueSnapshot(*element, property, *toCSSValue); 129 toStringPropertySpecificKeyframe(end)->m_animatableValueCache = to; 130 131 return LegacyStyleInterpolation::create(m_animatableValueCache.get(), to.release(), property); 132 } 133 134 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::PropertySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const 135 { 136 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, easing, 0, AnimationEffect::CompositeAdd)); 137 } 138 139 PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::PropertySpecificKeyframe::cloneWithOffset(double offset) const 140 { 141 Keyframe::PropertySpecificKeyframe* theClone = new PropertySpecificKeyframe(offset, m_easing, m_value.get()); 142 toStringPropertySpecificKeyframe(theClone)->m_animatableValueCache = m_animatableValueCache; 143 return adoptPtrWillBeNoop(theClone); 144 } 145 146 void StringKeyframe::PropertySpecificKeyframe::trace(Visitor* visitor) 147 { 148 visitor->trace(m_value); 149 visitor->trace(m_animatableValueCache); 150 Keyframe::PropertySpecificKeyframe::trace(visitor); 151 } 152 153 } 154