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 17namespace blink { 18 19StringKeyframe::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 25void 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 32PropertySet 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 42PassRefPtrWillBeRawPtr<Keyframe> StringKeyframe::clone() const 43{ 44 return adoptRefWillBeNoop(new StringKeyframe(*this)); 45} 46PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::createPropertySpecificKeyframe(CSSPropertyID property) const 47{ 48 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset(), &easing(), propertyValue(property), composite())); 49} 50 51void StringKeyframe::trace(Visitor* visitor) 52{ 53 visitor->trace(m_propertySet); 54 Keyframe::trace(visitor); 55} 56 57StringKeyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, PassRefPtr<TimingFunction> easing, CSSValue* value, AnimationEffect::CompositeOperation op) 58 : Keyframe::PropertySpecificKeyframe(offset, easing, op) 59 , m_value(value) 60{ } 61 62StringKeyframe::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 69PassRefPtrWillBeRawPtr<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 134PassOwnPtrWillBeRawPtr<Keyframe::PropertySpecificKeyframe> StringKeyframe::PropertySpecificKeyframe::neutralKeyframe(double offset, PassRefPtr<TimingFunction> easing) const 135{ 136 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, easing, 0, AnimationEffect::CompositeAdd)); 137} 138 139PassOwnPtrWillBeRawPtr<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 146void 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