1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef KeyframeAnimationEffect_h 32 #define KeyframeAnimationEffect_h 33 34 #include "core/animation/AnimatableValue.h" 35 #include "core/animation/AnimationEffect.h" 36 #include "wtf/HashMap.h" 37 #include "wtf/HashSet.h" 38 #include "wtf/PassOwnPtr.h" 39 #include "wtf/PassRefPtr.h" 40 #include "wtf/RefCounted.h" 41 #include "wtf/Vector.h" 42 43 namespace WebCore { 44 45 typedef HashSet<CSSPropertyID> PropertySet; 46 47 // Represents the keyframes set through the API. 48 class Keyframe : public RefCounted<Keyframe> { 49 public: 50 static PassRefPtr<Keyframe> create() 51 { 52 return adoptRef(new Keyframe); 53 } 54 static bool compareOffsets(const RefPtr<Keyframe>& a, const RefPtr<Keyframe>& b) 55 { 56 return a->offset() < b->offset(); 57 } 58 void setOffset(double offset) { m_offset = offset; } 59 double offset() const { return m_offset; } 60 void setComposite(AnimationEffect::CompositeOperation composite) { m_composite = composite; } 61 AnimationEffect::CompositeOperation composite() const { return m_composite; } 62 void setPropertyValue(CSSPropertyID, const AnimatableValue*); 63 void clearPropertyValue(CSSPropertyID); 64 const AnimatableValue* propertyValue(CSSPropertyID) const; 65 PropertySet properties() const; 66 PassRefPtr<Keyframe> clone() const { return adoptRef(new Keyframe(*this)); } 67 PassRefPtr<Keyframe> cloneWithOffset(double offset) const; 68 private: 69 Keyframe(); 70 Keyframe(const Keyframe&); 71 double m_offset; 72 AnimationEffect::CompositeOperation m_composite; 73 typedef HashMap<CSSPropertyID, RefPtr<AnimatableValue> > PropertyValueMap; 74 PropertyValueMap m_propertyValues; 75 }; 76 77 class KeyframeAnimationEffect : public AnimationEffect { 78 public: 79 class PropertySpecificKeyframe; 80 typedef Vector<RefPtr<Keyframe> > KeyframeVector; 81 typedef Vector<OwnPtr<KeyframeAnimationEffect::PropertySpecificKeyframe> > PropertySpecificKeyframeVector; 82 // FIXME: Implement accumulation. 83 static PassRefPtr<KeyframeAnimationEffect> create(const KeyframeVector& keyframes) 84 { 85 return adoptRef(new KeyframeAnimationEffect(keyframes)); 86 } 87 88 virtual bool affects(CSSPropertyID property) OVERRIDE 89 { 90 ensureKeyframeGroups(); 91 return m_keyframeGroups->contains(property); 92 } 93 94 // AnimationEffect implementation. 95 virtual PassOwnPtr<CompositableValueList> sample(int iteration, double fraction) const OVERRIDE; 96 97 // FIXME: Implement setFrames() 98 const KeyframeVector& getFrames() const { return m_keyframes; } 99 100 virtual bool isKeyframeAnimationEffect() const OVERRIDE { return true; } 101 102 PropertySet properties() const; 103 104 class PropertySpecificKeyframe { 105 public: 106 PropertySpecificKeyframe(double offset, const AnimatableValue*, CompositeOperation); 107 double offset() const { return m_offset; } 108 const CompositableValue* value() const { return m_value.get(); } 109 PassOwnPtr<PropertySpecificKeyframe> cloneWithOffset(double offset) const; 110 private: 111 // Used by cloneWithOffset(). 112 PropertySpecificKeyframe(double offset, PassRefPtr<CompositableValue>); 113 double m_offset; 114 RefPtr<CompositableValue> m_value; 115 }; 116 117 class PropertySpecificKeyframeGroup { 118 public: 119 void appendKeyframe(PassOwnPtr<PropertySpecificKeyframe>); 120 PassRefPtr<CompositableValue> sample(int iteration, double offset) const; 121 const PropertySpecificKeyframeVector& keyframes() const { return m_keyframes; } 122 private: 123 PropertySpecificKeyframeVector m_keyframes; 124 void removeRedundantKeyframes(); 125 void addSyntheticKeyframeIfRequired(); 126 127 friend class KeyframeAnimationEffect; 128 }; 129 130 const PropertySpecificKeyframeVector& getPropertySpecificKeyframes(CSSPropertyID id) const 131 { 132 ensureKeyframeGroups(); 133 return m_keyframeGroups->get(id)->keyframes(); 134 } 135 136 private: 137 KeyframeAnimationEffect(const KeyframeVector& keyframes); 138 139 KeyframeVector normalizedKeyframes() const; 140 // Lazily computes the groups of property-specific keyframes. 141 void ensureKeyframeGroups() const; 142 143 KeyframeVector m_keyframes; 144 // The spec describes filtering the normalized keyframes at sampling time 145 // to get the 'property-specific keyframes'. For efficiency, we cache the 146 // property-specific lists. 147 typedef HashMap<CSSPropertyID, OwnPtr<PropertySpecificKeyframeGroup> > KeyframeGroupMap; 148 mutable OwnPtr<KeyframeGroupMap> m_keyframeGroups; 149 }; 150 151 DEFINE_TYPE_CASTS(KeyframeAnimationEffect, AnimationEffect, value, value->isKeyframeAnimationEffect(), value.isKeyframeAnimationEffect()); 152 153 } // namespace WebCore 154 155 #endif // KeyframeAnimationEffect_h 156