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

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

Issue 194673002: Web Animations: Refactor KeyframeEffectModel to work via an InterpolationEffect. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@interpolationWrap
Patch Set: Created 6 years, 9 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 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 , m_after(const_cast<AnimationEffect::CompositableValue*>(after)) 80 , m_after(const_cast<AnimationEffect::CompositableValue*>(after))
81 , m_fraction(fraction) 81 , m_fraction(fraction)
82 , m_dependsOnUnderlyingValue(before->dependsOnUnderlyingValue() || after ->dependsOnUnderlyingValue()) 82 , m_dependsOnUnderlyingValue(before->dependsOnUnderlyingValue() || after ->dependsOnUnderlyingValue())
83 { } 83 { }
84 RefPtr<AnimationEffect::CompositableValue> m_before; 84 RefPtr<AnimationEffect::CompositableValue> m_before;
85 RefPtr<AnimationEffect::CompositableValue> m_after; 85 RefPtr<AnimationEffect::CompositableValue> m_after;
86 double m_fraction; 86 double m_fraction;
87 bool m_dependsOnUnderlyingValue; 87 bool m_dependsOnUnderlyingValue;
88 }; 88 };
89 89
90 const double accuracyForKeyframeEasing = 0.0000001;
91
92 } // namespace 90 } // namespace
93 91
94 92
95 namespace WebCore { 93 namespace WebCore {
96 94
97 Keyframe::Keyframe() 95 Keyframe::Keyframe()
98 : m_offset(nullValue()) 96 : m_offset(nullValue())
99 , m_composite(AnimationEffect::CompositeReplace) 97 , m_composite(AnimationEffect::CompositeReplace)
100 , m_easing(LinearTimingFunction::preset()) 98 , m_easing(LinearTimingFunction::preset())
101 { } 99 { }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 result = m_keyframes[0]->properties(); 161 result = m_keyframes[0]->properties();
164 for (size_t i = 1; i < m_keyframes.size(); i++) { 162 for (size_t i = 1; i < m_keyframes.size(); i++) {
165 PropertySet extras = m_keyframes[i]->properties(); 163 PropertySet extras = m_keyframes[i]->properties();
166 for (PropertySet::const_iterator it = extras.begin(); it != extras.end() ; ++it) { 164 for (PropertySet::const_iterator it = extras.begin(); it != extras.end() ; ++it) {
167 result.add(*it); 165 result.add(*it);
168 } 166 }
169 } 167 }
170 return result; 168 return result;
171 } 169 }
172 170
173 PassOwnPtr<AnimationEffect::CompositableValueList> KeyframeEffectModel::sample(i nt iteration, double fraction) const 171 PassOwnPtr<Vector<RefPtr<Interpolation> > > KeyframeEffectModel::sample(int iter ation, double fraction) const
174 { 172 {
175 ASSERT(iteration >= 0); 173 ASSERT(iteration >= 0);
176 ASSERT(!isNull(fraction)); 174 ASSERT(!isNull(fraction));
177 const_cast<KeyframeEffectModel*>(this)->ensureKeyframeGroups(); 175 ensureKeyframeGroups();
178 OwnPtr<CompositableValueList> map = adoptPtr(new CompositableValueList()); 176 ensureInterpolationEffect();
179 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter != m_keyframeGroups->end(); ++iter) 177
180 map->append(std::make_pair(iter->key, iter->value->sample(iteration, fra ction))); 178 return m_interpolationEffect->getActiveInterpolations(fraction);
181 return map.release();
182 } 179 }
183 180
184 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con st KeyframeVector& keyframes) 181 KeyframeEffectModel::KeyframeVector KeyframeEffectModel::normalizedKeyframes(con st KeyframeVector& keyframes)
185 { 182 {
186 // keyframes [beginIndex, endIndex) will remain after removing all keyframes if they are not 183 // keyframes [beginIndex, endIndex) will remain after removing all keyframes if they are not
187 // loosely sorted by offset, and after removing keyframes with positional of fset outide [0, 1]. 184 // loosely sorted by offset, and after removing keyframes with positional of fset outide [0, 1].
188 size_t beginIndex = 0; 185 size_t beginIndex = 0;
189 size_t endIndex = keyframes.size(); 186 size_t endIndex = keyframes.size();
190 187
191 // Becomes the most recent keyframe with an explicit offset. 188 // Becomes the most recent keyframe with an explicit offset.
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 } 266 }
270 } 267 }
271 268
272 // Add synthetic keyframes. 269 // Add synthetic keyframes.
273 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) { 270 for (KeyframeGroupMap::iterator iter = m_keyframeGroups->begin(); iter != m_ keyframeGroups->end(); ++iter) {
274 iter->value->addSyntheticKeyframeIfRequired(); 271 iter->value->addSyntheticKeyframeIfRequired();
275 iter->value->removeRedundantKeyframes(); 272 iter->value->removeRedundantKeyframes();
276 } 273 }
277 } 274 }
278 275
276 void KeyframeEffectModel::ensureInterpolationEffect() const
277 {
278 if (m_interpolationEffect)
279 return;
280 m_interpolationEffect = InterpolationEffect::create();
281
282 for (KeyframeGroupMap::const_iterator iter = m_keyframeGroups->begin(); iter != m_keyframeGroups->end(); ++iter) {
283 const PropertySpecificKeyframeVector& keyframes = iter->value->keyframes ();
284 ASSERT(keyframes[0]->value()->isAnimatableValue());
285 const AnimatableValue* start;
286 const AnimatableValue* end = toAnimatableValue(keyframes[0]->value());
287 for (size_t i = 0; i < keyframes.size() - 1; i++) {
288 ASSERT(keyframes[i + 1]->value()->isAnimatableValue());
289 start = end;
290 end = toAnimatableValue(keyframes[i + 1]->value());
291 double applyFrom = i ? keyframes[i]->offset() : (-std::numeric_limit s<double>::infinity());
292 double applyTo = i == keyframes.size() - 2 ? std::numeric_limits<dou ble>::infinity() : keyframes[i+1]->offset();
293 if (applyTo == 1)
294 applyTo = std::numeric_limits<double>::infinity();
295 m_interpolationEffect->addInterpolation(
296 LegacyStyleInterpolation::create(
297 AnimatableValue::takeConstRef(start),
298 AnimatableValue::takeConstRef(end), iter->key),
299 keyframes[i]->easing(), keyframes[i]->offset(), keyframes[i+1]-> offset(), applyFrom, applyTo);
300 }
301 }
302 }
279 303
280 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit eOperation composite) 304 KeyframeEffectModel::PropertySpecificKeyframe::PropertySpecificKeyframe(double o ffset, PassRefPtr<TimingFunction> easing, const AnimatableValue* value, Composit eOperation composite)
281 : m_offset(offset) 305 : m_offset(offset)
282 , m_easing(easing) 306 , m_easing(easing)
283 , m_value(composite == AnimationEffect::CompositeReplace ? 307 , m_value(composite == AnimationEffect::CompositeReplace ?
284 AnimatableValue::takeConstRef(value) : 308 AnimatableValue::takeConstRef(value) :
285 static_cast<PassRefPtr<CompositableValue> >(AddCompositableValue::create (value))) 309 static_cast<PassRefPtr<CompositableValue> >(AddCompositableValue::create (value)))
286 { 310 {
287 } 311 }
288 312
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 } 362 }
339 if (!allOffsetsEqual) 363 if (!allOffsetsEqual)
340 return; 364 return;
341 365
342 if (!offset) 366 if (!offset)
343 appendKeyframe(m_keyframes.first()->cloneWithOffset(1.0)); 367 appendKeyframe(m_keyframes.first()->cloneWithOffset(1.0));
344 else 368 else
345 m_keyframes.insert(0, adoptPtr(new PropertySpecificKeyframe(0.0, nullptr , AnimatableValue::neutralValue(), CompositeAdd))); 369 m_keyframes.insert(0, adoptPtr(new PropertySpecificKeyframe(0.0, nullptr , AnimatableValue::neutralValue(), CompositeAdd)));
346 } 370 }
347 371
348 PassRefPtr<AnimationEffect::CompositableValue> KeyframeEffectModel::PropertySpec ificKeyframeGroup::sample(int iteration, double offset) const
349 {
350 // FIXME: Implement accumulation.
351 ASSERT_UNUSED(iteration, iteration >= 0);
352 ASSERT(!isNull(offset));
353
354 // Bail if offset is null, as this can lead to buffer overflow below.
355 if (isNull(offset))
356 return const_cast<CompositableValue*>(m_keyframes.first()->value());
357
358 double minimumOffset = m_keyframes.first()->offset();
359 double maximumOffset = m_keyframes.last()->offset();
360 ASSERT(minimumOffset != maximumOffset);
361
362 PropertySpecificKeyframeVector::const_iterator before;
363 PropertySpecificKeyframeVector::const_iterator after;
364
365 // Note that this algorithm is simpler than that in the spec because we
366 // have removed keyframes with equal offsets in
367 // removeRedundantKeyframes().
368 if (offset < minimumOffset) {
369 before = m_keyframes.begin();
370 after = before + 1;
371 ASSERT((*before)->offset() > offset);
372 ASSERT((*after)->offset() > offset);
373 } else if (offset >= maximumOffset) {
374 after = m_keyframes.end() - 1;
375 before = after - 1;
376 ASSERT((*before)->offset() < offset);
377 ASSERT((*after)->offset() <= offset);
378 } else {
379 // FIXME: This is inefficient for large numbers of keyframes. Consider
380 // using binary search.
381 after = m_keyframes.begin();
382 while ((*after)->offset() <= offset)
383 ++after;
384 before = after - 1;
385 ASSERT((*before)->offset() <= offset);
386 ASSERT((*after)->offset() > offset);
387 }
388
389 if ((*before)->offset() == offset)
390 return const_cast<CompositableValue*>((*before)->value());
391 if ((*after)->offset() == offset)
392 return const_cast<CompositableValue*>((*after)->value());
393
394 double fraction = (offset - (*before)->offset()) / ((*after)->offset() - (*b efore)->offset());
395 if (const TimingFunction* timingFunction = (*before)->easing())
396 fraction = timingFunction->evaluate(fraction, accuracyForKeyframeEasing) ;
397 return BlendedCompositableValue::create((*before)->value(), (*after)->value( ), fraction);
398 }
399
400 void KeyframeEffectModel::trace(Visitor* visitor) 372 void KeyframeEffectModel::trace(Visitor* visitor)
401 { 373 {
402 visitor->trace(m_keyframes); 374 visitor->trace(m_keyframes);
403 } 375 }
404 376
405 } // namespace 377 } // 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