Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: Source/core/animation/KeyframeEffectModel.cpp

Issue 215883005: Web Animations: Introduce String based KeyframeEffectModel (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 18 matching lines...) Expand all
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/animation/KeyframeEffectModel.h" 32 #include "core/animation/KeyframeEffectModel.h"
33 33
34 #include "core/animation/TimedItem.h" 34 #include "core/animation/TimedItem.h"
35 #include "wtf/text/StringHash.h" 35 #include "wtf/text/StringHash.h"
36 36
37 namespace WebCore { 37 namespace WebCore {
38 38
39 Keyframe::Keyframe() 39 bool Keyframe::compareOffsets(const RefPtrWillBeRawPtr<Keyframe>& a, const RefPt rWillBeRawPtr<Keyframe>& b)
40 : m_offset(nullValue())
41 , m_composite(AnimationEffect::CompositeReplace)
42 , m_easing(LinearTimingFunction::preset())
43 { }
44
45 Keyframe::Keyframe(const Keyframe& copyFrom)
46 : m_offset(copyFrom.m_offset)
47 , m_composite(copyFrom.m_composite)
48 , m_easing(copyFrom.m_easing)
49 { 40 {
50 ASSERT(m_easing); 41 return a->offset() < b->offset();
51 for (PropertyValueMap::const_iterator iter = copyFrom.m_propertyValues.begin (); iter != copyFrom.m_propertyValues.end(); ++iter)
52 setPropertyValue(iter->key, iter->value.get());
53 } 42 }
54 43
55 void Keyframe::setEasing(PassRefPtr<TimingFunction> easing) 44 PropertySet KeyframeEffectModelBase::properties() const
56 {
57 ASSERT(easing);
58 m_easing = easing;
59 }
60
61 void Keyframe::setPropertyValue(CSSPropertyID property, const AnimatableValue* v alue)
62 {
63 m_propertyValues.add(property, const_cast<AnimatableValue*>(value));
64 }
65
66 void Keyframe::clearPropertyValue(CSSPropertyID property)
67 {
68 m_propertyValues.remove(property);
69 }
70
71 const AnimatableValue* Keyframe::propertyValue(CSSPropertyID property) const
72 {
73 ASSERT(m_propertyValues.contains(property));
74 return m_propertyValues.get(property);
75 }
76
77 PropertySet Keyframe::properties() const
78 {
79 // This is not used in time-critical code, so we probably don't need to
80 // worry about caching this result.
81 PropertySet properties;
82 for (PropertyValueMap::const_iterator iter = m_propertyValues.begin(); iter != m_propertyValues.end(); ++iter)
83 properties.add(*iter.keys());
84 return properties;
85 }
86
87 PassRefPtrWillBeRawPtr<Keyframe> Keyframe::cloneWithOffset(double offset) const
88 {
89 RefPtrWillBeRawPtr<Keyframe> theClone = clone();
90 theClone->setOffset(offset);
91 return theClone.release();
92 }
93
94 void Keyframe::trace(Visitor* visitor)
95 {
96 visitor->trace(m_propertyValues);
97 }
98
99 KeyframeEffectModel::KeyframeEffectModel(const KeyframeVector& keyframes)
100 : m_keyframes(keyframes)
101 {
102 }
103
104 PropertySet KeyframeEffectModel::properties() const
105 { 45 {
106 PropertySet result; 46 PropertySet result;
107 if (!m_keyframes.size()) { 47 if (!m_keyframes.size()) {
108 return result; 48 return result;
109 } 49 }
110 result = m_keyframes[0]->properties(); 50 result = m_keyframes[0]->properties();
111 for (size_t i = 1; i < m_keyframes.size(); i++) { 51 for (size_t i = 1; i < m_keyframes.size(); i++) {
112 PropertySet extras = m_keyframes[i]->properties(); 52 PropertySet extras = m_keyframes[i]->properties();
113 for (PropertySet::const_iterator it = extras.begin(); it != extras.end() ; ++it) { 53 for (PropertySet::const_iterator it = extras.begin(); it != extras.end() ; ++it) {
114 result.add(*it); 54 result.add(*it);
115 } 55 }
116 } 56 }
117 return result; 57 return result;
118 } 58 }
119 59
120 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > Ke yframeEffectModel::sample(int iteration, double fraction, double iterationDurati on) const 60 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation> > > Ke yframeEffectModelBase::sample(int iteration, double fraction, double iterationDu ration) const
121 { 61 {
122 ASSERT(iteration >= 0); 62 ASSERT(iteration >= 0);
123 ASSERT(!isNull(fraction)); 63 ASSERT(!isNull(fraction));
124 ensureKeyframeGroups(); 64 ensureKeyframeGroups();
125 ensureInterpolationEffect(); 65 ensureInterpolationEffect();
126 66
127 return m_interpolationEffect->getActiveInterpolations(fraction, iterationDur ation); 67 return m_interpolationEffect->getActiveInterpolations(fraction, iterationDur ation);
128 } 68 }
129 69
130 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con st KeyframeVector& keyframes) 70 KeyframeEffectModelBase::KeyframeVector KeyframeEffectModelBase::normalizedKeyfr ames(const KeyframeVector& keyframes)
131 { 71 {
132 // keyframes [beginIndex, endIndex) will remain after removing all keyframes if they are not 72 // keyframes [beginIndex, endIndex) will remain after removing all keyframes if they are not
133 // loosely sorted by offset, and after removing keyframes with positional of fset outide [0, 1]. 73 // loosely sorted by offset, and after removing keyframes with positional of fset outide [0, 1].
134 size_t beginIndex = 0; 74 size_t beginIndex = 0;
135 size_t endIndex = keyframes.size(); 75 size_t endIndex = keyframes.size();
136 76
137 // Becomes the most recent keyframe with an explicit offset. 77 // Becomes the most recent keyframe with an explicit offset.
138 size_t lastIndex = endIndex; 78 size_t lastIndex = endIndex;
139 double lastOffset = std::numeric_limits<double>::quiet_NaN(); 79 double lastOffset = std::numeric_limits<double>::quiet_NaN();
140 80
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 result[lastIndex + j]->setOffset(lastOffset + (offset - lastOffset) * j / (i - lastIndex)); 124 result[lastIndex + j]->setOffset(lastOffset + (offset - lastOffset) * j / (i - lastIndex));
185 } 125 }
186 lastIndex = i; 126 lastIndex = i;
187 lastOffset = offset; 127 lastOffset = offset;
188 } 128 }
189 } 129 }
190 } 130 }
191 return result; 131 return result;
192 } 132 }
193 133
194 void KeyframeEffectModel::ensureKeyframeGroups() const 134
135 void KeyframeEffectModelBase::ensureKeyframeGroups() const
195 { 136 {
196 if (m_keyframeGroups) 137 if (m_keyframeGroups)
197 return; 138 return;
198 139
199 m_keyframeGroups = adoptPtrWillBeNoop(new KeyframeGroupMap); 140 m_keyframeGroups = adoptPtrWillBeNoop(new KeyframeGroupMap);
200 const KeyframeVector keyframes = normalizedKeyframes(getFrames()); 141 const KeyframeVector keyframes = normalizedKeyframes(getFrames());
201 for (KeyframeVector::const_iterator keyframeIter = keyframes.begin(); keyfra meIter != keyframes.end(); ++keyframeIter) { 142 for (KeyframeVector::const_iterator keyframeIter = keyframes.begin(); keyfra meIter != keyframes.end(); ++keyframeIter) {
202 const Keyframe* keyframe = keyframeIter->get(); 143 const Keyframe* keyframe = keyframeIter->get();
203 PropertySet keyframeProperties = keyframe->properties(); 144 PropertySet keyframeProperties = keyframe->properties();
204 for (PropertySet::const_iterator propertyIter = keyframeProperties.begin (); propertyIter != keyframeProperties.end(); ++propertyIter) { 145 for (PropertySet::const_iterator propertyIter = keyframeProperties.begin (); propertyIter != keyframeProperties.end(); ++propertyIter) {
205 CSSPropertyID property = *propertyIter; 146 CSSPropertyID property = *propertyIter;
206 KeyframeGroupMap::iterator groupIter = m_keyframeGroups->find(proper ty); 147 KeyframeGroupMap::iterator groupIter = m_keyframeGroups->find(proper ty);
207 PropertySpecificKeyframeGroup* group; 148 PropertySpecificKeyframeGroup* group;
208 if (groupIter == m_keyframeGroups->end()) 149 if (groupIter == m_keyframeGroups->end())
209 group = m_keyframeGroups->add(property, adoptPtrWillBeNoop(new P ropertySpecificKeyframeGroup)).storedValue->value.get(); 150 group = m_keyframeGroups->add(property, adoptPtrWillBeNoop(new P ropertySpecificKeyframeGroup)).storedValue->value.get();
210 else 151 else
211 group = groupIter->value.get(); 152 group = groupIter->value.get();
212 153
213 ASSERT(keyframe->composite() == AnimationEffect::CompositeReplace); 154 ASSERT(keyframe->composite() == AnimationEffect::CompositeReplace);
214 group->appendKeyframe(adoptPtrWillBeNoop( 155 group->appendKeyframe(keyframe->createPropertySpecificKeyframe(prope rty));
215 new PropertySpecificKeyframe(keyframe->offset(), keyframe->easin g(), keyframe->propertyValue(property), keyframe->composite())));
216 } 156 }
217 } 157 }
218 158
219 // Add synthetic keyframes. 159 // Add synthetic keyframes.
220 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) { 160 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) {
221 iter->value->addSyntheticKeyframeIfRequired(); 161 iter->value->addSyntheticKeyframeIfRequired(this);
222 iter->value->removeRedundantKeyframes(); 162 iter->value->removeRedundantKeyframes();
223 } 163 }
224 } 164 }
225 165
226 void KeyframeEffectModel::ensureInterpolationEffect() const 166 void KeyframeEffectModelBase::ensureInterpolationEffect() const
227 { 167 {
228 if (m_interpolationEffect) 168 if (m_interpolationEffect)
229 return; 169 return;
230 m_interpolationEffect = InterpolationEffect::create(); 170 m_interpolationEffect = InterpolationEffect::create();
231 171
232 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter != m_keyframeGroups->end(); ++iter) { 172 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter != m_keyframeGroups->end(); ++iter) {
233 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes (); 173 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes ();
234 ASSERT(keyframes[0]->composite() == AnimationEffect::CompositeReplace); 174 ASSERT(keyframes[0]->composite() == AnimationEffect::CompositeReplace);
235 const AnimatableValue* start;
236 const AnimatableValue* end = keyframes[0]->value();
237 for (size_t i = 0; i < keyframes.size() - 1; i++) { 175 for (size_t i = 0; i < keyframes.size() - 1; i++) {
238 ASSERT(keyframes[i + 1]->composite() == AnimationEffect::CompositeRe place); 176 ASSERT(keyframes[i + 1]->composite() == AnimationEffect::CompositeRe place);
239 start = end;
240 end = keyframes[i + 1]->value();
241 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit s<double>::infinity()); 177 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit s<double>::infinity());
242 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou ble>::infinity() : keyframes[i + 1]->offset(); 178 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou ble>::infinity() : keyframes[i + 1]->offset();
243 if (applyTo == 1) 179 if (applyTo == 1)
244 applyTo = std::numeric_limits<double>::infinity(); 180 applyTo = std::numeric_limits<double>::infinity();
245 m_interpolationEffect->addInterpolation( 181
246 LegacyStyleInterpolation::create( 182 m_interpolationEffect->addInterpolation(keyframes[i]->createInterpol ation(iter->key, keyframes[i + 1].get()),
247 AnimatableValue::takeConstRef(start),
248 AnimatableValue::takeConstRef(end), iter->key),
249 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i + 1] ->offset(), applyFrom, applyTo); 183 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i + 1] ->offset(), applyFrom, applyTo);
250 } 184 }
251 } 185 }
252 } 186 }
253 187
254 bool KeyframeEffectModel::isReplaceOnly() 188 bool KeyframeEffectModelBase::isReplaceOnly()
255 { 189 {
256 ensureKeyframeGroups(); 190 ensureKeyframeGroups();
257 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) { 191 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) {
258 const PropertySpecificKeyframeVector& keyframeVector = iter->value->keyf rames(); 192 const PropertySpecificKeyframeVector& keyframeVector = iter->value->keyf rames();
259 for (size_t i = 0; i < keyframeVector.size(); ++i) { 193 for (size_t i = 0; i < keyframeVector.size(); ++i) {
260 if (keyframeVector[i]->composite() != AnimationEffect::CompositeRepl ace) 194 if (keyframeVector[i]->composite() != AnimationEffect::CompositeRepl ace)
261 return false; 195 return false;
262 } 196 }
263 } 197 }
264 return true; 198 return true;
265 } 199 }
266 200
267 void KeyframeEffectModel::trace(Visitor* visitor) 201 void KeyframeEffectModelBase::trace(Visitor* visitor)
268 { 202 {
269 visitor->trace(m_keyframes); 203 visitor->trace(m_keyframes);
270 visitor->trace(m_interpolationEffect); 204 visitor->trace(m_interpolationEffect);
271 #if ENABLE_OILPAN 205 #if ENABLE_OILPAN
272 visitor->trace(m_keyframeGroups); 206 visitor->trace(m_keyframeGroups);
273 #endif 207 #endif
274 } 208 }
275 209
276 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit eOperation composite) 210 Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(double offset, Pass RefPtr<TimingFunction> easing, AnimationEffect::CompositeOperation composite)
277 : m_offset(offset) 211 : m_offset(offset)
278 , m_easing(easing) 212 , m_easing(easing)
279 , m_composite(composite) 213 , m_composite(composite)
280 { 214 {
281 m_value = AnimatableValue::takeConstRef(value);
282 } 215 }
283 216
284 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o ffset, PassRefPtr<TimingFunction> easing, PassRefPtrWillBeRawPtr<AnimatableValue > value, CompositeOperation composite) 217 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::appendKeyframe(Pass OwnPtr<PropertySpecificKeyframe> keyframe)
285 : m_offset(offset)
286 , m_easing(easing)
287 , m_value(value)
288 , m_composite(composite)
289 {
290 ASSERT(!isNull(m_offset));
291 }
292
293 PassOwnPtrWillBeRawPtr<KeyframeEffectModel::PropertySpecificKeyframe> KeyframeEf fectModel::PropertySpecificKeyframe::cloneWithOffset(double offset) const
294 {
295 return adoptPtrWillBeNoop(new PropertySpecificKeyframe(offset, m_easing, m_v alue.get(), m_composite));
296 }
297
298 void KeyframeEffectModel::PropertySpecificKeyframe::trace(Visitor* visitor)
299 {
300 visitor->trace(m_value);
301 }
302
303 void KeyframeEffectModel::PropertySpecificKeyframeGroup::appendKeyframe(PassOwnP trWillBeRawPtr<PropertySpecificKeyframe> keyframe)
304 { 218 {
305 ASSERT(m_keyframes.isEmpty() || m_keyframes.last()->offset() <= keyframe->of fset()); 219 ASSERT(m_keyframes.isEmpty() || m_keyframes.last()->offset() <= keyframe->of fset());
306 m_keyframes.append(keyframe); 220 m_keyframes.append(keyframe);
307 } 221 }
308 222
309 void KeyframeEffectModel::PropertySpecificKeyframeGroup::removeRedundantKeyframe s() 223 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::removeRedundantKeyf rames()
310 { 224 {
311 // As an optimization, removes keyframes in the following categories, as 225 // As an optimization, removes keyframes in the following categories, as
312 // they will never be used by sample(). 226 // they will never be used by sample().
313 // - End keyframes with the same offset as their neighbor 227 // - End keyframes with the same offset as their neighbor
314 // - Interior keyframes with the same offset as both their neighbors 228 // - Interior keyframes with the same offset as both their neighbors
315 // Note that synthetic keyframes must be added before this method is 229 // Note that synthetic keyframes must be added before this method is
316 // called. 230 // called.
317 ASSERT(m_keyframes.size() >= 2); 231 ASSERT(m_keyframes.size() >= 2);
318 for (int i = m_keyframes.size() - 1; i >= 0; --i) { 232 for (int i = m_keyframes.size() - 1; i >= 0; --i) {
319 double offset = m_keyframes[i]->offset(); 233 double offset = m_keyframes[i]->offset();
320 bool hasSameOffsetAsPreviousNeighbor = !i || m_keyframes[i - 1]->offset( ) == offset; 234 bool hasSameOffsetAsPreviousNeighbor = !i || m_keyframes[i - 1]->offset( ) == offset;
321 bool hasSameOffsetAsNextNeighbor = i == static_cast<int>(m_keyframes.siz e() - 1) || m_keyframes[i + 1]->offset() == offset; 235 bool hasSameOffsetAsNextNeighbor = i == static_cast<int>(m_keyframes.siz e() - 1) || m_keyframes[i + 1]->offset() == offset;
322 if (hasSameOffsetAsPreviousNeighbor && hasSameOffsetAsNextNeighbor) 236 if (hasSameOffsetAsPreviousNeighbor && hasSameOffsetAsNextNeighbor)
323 m_keyframes.remove(i); 237 m_keyframes.remove(i);
324 } 238 }
325 ASSERT(m_keyframes.size() >= 2); 239 ASSERT(m_keyframes.size() >= 2);
326 } 240 }
327 241
328 void KeyframeEffectModel::PropertySpecificKeyframeGroup::addSyntheticKeyframeIfR equired() 242 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::addSyntheticKeyfram eIfRequired(const KeyframeEffectModelBase* context)
329 { 243 {
330 ASSERT(!m_keyframes.isEmpty()); 244 ASSERT(!m_keyframes.isEmpty());
331 if (m_keyframes.first()->offset() != 0.0) 245 if (m_keyframes.first()->offset() != 0.0)
332 m_keyframes.insert(0, adoptPtrWillBeNoop(new PropertySpecificKeyframe(0, nullptr, AnimatableValue::neutralValue(), CompositeAdd))); 246 m_keyframes.insert(0, m_keyframes.first()->neutralKeyframe(0, nullptr));
333 if (m_keyframes.last()->offset() != 1.0) 247 if (m_keyframes.last()->offset() != 1.0)
334 appendKeyframe(adoptPtrWillBeNoop(new PropertySpecificKeyframe(1, nullpt r, AnimatableValue::neutralValue(), CompositeAdd))); 248 appendKeyframe(m_keyframes.last()->neutralKeyframe(1, nullptr));
335 } 249 }
336 250
337 void KeyframeEffectModel::PropertySpecificKeyframeGroup::trace(Visitor* visitor) 251 void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::trace(Visitor* visi tor)
338 { 252 {
339 #if ENABLE_OILPAN 253 #if ENABLE(OILPAN)
340 visitor->trace(m_keyframes); 254 visitor->trace(m_keyframes);
341 #endif 255 #endif
342 } 256 }
343 257
258 template <>
259 bool KeyframeEffectModel<AnimatableValueKeyframe>::isAnimatableValueKeyframeEffe ctModel() const { return true; }
260
261 template <>
262 bool KeyframeEffectModel<StringKeyframe>::isStringKeyframeEffectModel() const { return true; }
263
344 } // namespace 264 } // namespace
OLDNEW
« no previous file with comments | « Source/core/animation/KeyframeEffectModel.h ('k') | Source/core/animation/KeyframeEffectModelTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698