[BlackBerry] Upstream LayerAnimation.{cpp, h}
[WebKit-https.git] / Source / WebCore / platform / graphics / blackberry / LayerAnimation.cpp
1 /*
2  * Copyright (C) 2011, 2012 Research In Motion Limited. All rights reserved.
3  * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1.  Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  * 2.  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15  *     its contributors may be used to endorse or promote products derived
16  *     from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "config.h"
31 #include "LayerAnimation.h"
32
33 #include "IdentityTransformOperation.h"
34 #include "LayerCompositingThread.h"
35 #include "TransformationMatrix.h"
36 #include "UnitBezier.h"
37
38 #include <algorithm>
39
40 namespace WebCore {
41
42 using namespace std;
43
44 // FIXME: Some functions below are copied from AnimationBase and KeyframeAnimation.
45 // We need to refactor these code to increase code reuse.
46 // https://bugs.webkit.org/show_bug.cgi?id=82293
47
48 // The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the
49 // animation, the more precision we need in the timing function result to avoid ugly discontinuities.
50 static inline double solveEpsilon(double duration)
51 {
52     return 1.0 / (200.0 * duration);
53 }
54
55 static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x, double p2y, double t, double duration)
56 {
57     // Convert from input time to parametric value in curve, then from
58     // that to output time.
59     UnitBezier bezier(p1x, p1y, p2x, p2y);
60     return bezier.solve(t, solveEpsilon(duration));
61 }
62
63 static inline double solveStepsFunction(int numSteps, bool stepAtStart, double t)
64 {
65     if (stepAtStart)
66         return min(1.0, (floor(numSteps * t) + 1) / numSteps);
67     return floor(numSteps * t) / numSteps;
68 }
69
70 static const TimingFunction* timingFunctionForAnimationValue(const AnimationValue* animValue, const LayerAnimation* anim)
71 {
72     if (animValue->timingFunction())
73         return animValue->timingFunction();
74     if (anim->timingFunction())
75         return anim->timingFunction();
76
77     return CubicBezierTimingFunction::defaultTimingFunction();
78 }
79
80 static double progress(double elapsedTime, const LayerAnimation* layerAnimation, double scale, double offset, const TimingFunction* tf)
81 {
82     double dur = layerAnimation->duration();
83     if (layerAnimation->iterationCount() > 0)
84         dur *= layerAnimation->iterationCount();
85
86     if (!layerAnimation->duration())
87         return 1.0;
88     if (layerAnimation->iterationCount() > 0 && elapsedTime >= dur)
89         return (layerAnimation->iterationCount() % 2) ? 1.0 : 0.0;
90
91     // Compute the fractional time, taking into account direction.
92     // There is no need to worry about iterations, we assume that we would have
93     // short circuited above if we were done.
94     double fractionalTime = elapsedTime / layerAnimation->duration();
95     int integralTime = static_cast<int>(fractionalTime);
96     fractionalTime -= integralTime;
97
98     if ((layerAnimation->direction() == Animation::AnimationDirectionAlternate) && (integralTime & 1))
99         fractionalTime = 1 - fractionalTime;
100
101     if (scale != 1 || offset)
102         fractionalTime = (fractionalTime - offset) * scale;
103
104     if (!tf)
105         tf = layerAnimation->timingFunction();
106
107     if (tf->isCubicBezierTimingFunction()) {
108         const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(tf);
109         return solveCubicBezierFunction(ctf->x1(), ctf->y1(), ctf->x2(), ctf->y2(), fractionalTime, layerAnimation->duration());
110     }
111
112     if (tf->isStepsTimingFunction()) {
113         const StepsTimingFunction* stf = static_cast<const StepsTimingFunction*>(tf);
114         return solveStepsFunction(stf->numberOfSteps(), stf->stepAtStart(), fractionalTime);
115     }
116
117     return fractionalTime;
118 }
119
120 static void fetchIntervalEndpoints(double elapsedTime, const LayerAnimation* layerAnimation, const AnimationValue*& fromValue, const AnimationValue*& toValue, double& prog)
121 {
122     // Find the first key.
123     if (layerAnimation->duration() && layerAnimation->iterationCount() != Animation::IterationCountInfinite)
124         elapsedTime = min(elapsedTime, layerAnimation->duration() * layerAnimation->iterationCount());
125
126     double fractionalTime = layerAnimation->duration() ? (elapsedTime / layerAnimation->duration()) : 1;
127
128     // FIXME: startTime can be before the current animation "frame" time. This is to sync with the frame time
129     // concept in AnimationTimeController. So we need to somehow sync the two. Until then, the possible
130     // error is small and will probably not be noticeable. Until we fix this, remove the assert.
131     // https://bugs.webkit.org/show_bug.cgi?id=52037
132     // ASSERT(fractionalTime >= 0);
133     if (fractionalTime < 0)
134         fractionalTime = 0;
135
136     // FIXME: share this code with AnimationBase::progress().
137     int iteration = static_cast<int>(fractionalTime);
138     if (layerAnimation->iterationCount() != Animation::IterationCountInfinite)
139         iteration = min(iteration, layerAnimation->iterationCount() - 1);
140
141     fractionalTime -= iteration;
142
143     bool reversing = (layerAnimation->direction() == Animation::AnimationDirectionAlternate) && (iteration & 1);
144     if (reversing)
145         fractionalTime = 1 - fractionalTime;
146
147     size_t numKeyframes = layerAnimation->valueCount();
148     if (!numKeyframes)
149         return;
150
151     ASSERT(!layerAnimation->valueAt(0)->keyTime());
152     ASSERT(layerAnimation->valueAt(layerAnimation->valueCount() - 1)->keyTime() == 1);
153
154     int prevIndex = -1;
155     int nextIndex = -1;
156
157     // FIXME: with a lot of keys, this linear search will be slow. We could binary search.
158     for (size_t i = 0; i < numKeyframes; ++i) {
159         const AnimationValue* currKeyframe = layerAnimation->valueAt(i);
160
161         if (fractionalTime < currKeyframe->keyTime()) {
162             nextIndex = i;
163             break;
164         }
165
166         prevIndex = i;
167     }
168
169     double scale = 1;
170     double offset = 0;
171
172     if (prevIndex == -1)
173         prevIndex = 0;
174
175     if (nextIndex == -1)
176         nextIndex = layerAnimation->valueCount() - 1;
177
178     const AnimationValue* prevKeyframe = layerAnimation->valueAt(prevIndex);
179     const AnimationValue* nextKeyframe = layerAnimation->valueAt(nextIndex);
180
181     fromValue = prevKeyframe;
182     toValue = nextKeyframe;
183
184     offset = prevKeyframe->keyTime();
185     scale = 1.0 / (nextKeyframe->keyTime() - prevKeyframe->keyTime());
186
187     const TimingFunction* timingFunction = timingFunctionForAnimationValue(prevKeyframe, layerAnimation);
188
189     prog = progress(elapsedTime, layerAnimation, scale, offset, timingFunction);
190 }
191
192 void LayerAnimation::apply(LayerCompositingThread* layer, double elapsedTime)
193 {
194     const AnimationValue* from = 0;
195     const AnimationValue* to = 0;
196     double progress = 0.0;
197
198     fetchIntervalEndpoints(elapsedTime, this, from, to, progress);
199
200     switch (property()) {
201     case AnimatedPropertyWebkitTransform:
202         layer->setTransform(blendTransform(static_cast<const TransformAnimationValue*>(from)->value(), static_cast<const TransformAnimationValue*>(to)->value(), progress));
203         break;
204     case AnimatedPropertyOpacity:
205         layer->setOpacity(blendOpacity(static_cast<const FloatAnimationValue*>(from)->value(), static_cast<const FloatAnimationValue*>(to)->value(), progress));
206         break;
207     case AnimatedPropertyBackgroundColor:
208     case AnimatedPropertyWebkitFilter:
209     case AnimatedPropertyInvalid:
210         ASSERT_NOT_REACHED();
211         break;
212     }
213 }
214
215 TransformationMatrix LayerAnimation::blendTransform(const TransformOperations* from, const TransformOperations* to, double progress) const
216 {
217     TransformationMatrix t;
218
219     if (m_transformFunctionListValid) {
220         // A trick to avoid touching the refcount of shared TransformOperations on the wrong thread.
221         // Since TransforOperation is not ThreadSafeRefCounted, we are only allowed to touch the ref
222         // count of shared operations when the WebKit thread and compositing thread are in sync.
223         Vector<TransformOperation*> result;
224         Vector<RefPtr<TransformOperation> > owned;
225
226         unsigned fromSize = from->operations().size();
227         unsigned toSize = to->operations().size();
228         unsigned size = max(fromSize, toSize);
229         for (unsigned i = 0; i < size; i++) {
230             TransformOperation* fromOp = (i < fromSize) ? from->operations()[i].get() : 0;
231             TransformOperation* toOp = (i < toSize) ? to->operations()[i].get() : 0;
232             RefPtr<TransformOperation> blendedOp = toOp ? toOp->blend(fromOp, progress) : (fromOp ? fromOp->blend(0, progress, true) : PassRefPtr<TransformOperation>(0));
233             if (blendedOp) {
234                 result.append(blendedOp.get());
235                 owned.append(blendedOp);
236             } else {
237                 RefPtr<TransformOperation> identityOp = IdentityTransformOperation::create();
238                 owned.append(identityOp);
239                 if (progress > 0.5)
240                     result.append(toOp ? toOp : identityOp.get());
241                 else
242                     result.append(fromOp ? fromOp : identityOp.get());
243             }
244         }
245
246         IntSize sz = boxSize();
247         for (unsigned i = 0; i < result.size(); ++i)
248             result[i]->apply(t, sz);
249     } else {
250         // Convert the TransformOperations into matrices.
251         TransformationMatrix fromT;
252         from->apply(boxSize(), fromT);
253         to->apply(boxSize(), t);
254
255         t.blend(fromT, progress);
256     }
257
258     return t;
259 }
260
261 float LayerAnimation::blendOpacity(float from, float to, double progress) const
262 {
263     float opacity = from + (to - from) * progress;
264
265     return max(0.0f, min(opacity, 1.0f));
266 }
267
268 void LayerAnimation::validateTransformLists()
269 {
270     m_transformFunctionListValid = false;
271
272     if (m_values.size() < 2 || property() != AnimatedPropertyWebkitTransform)
273         return;
274
275     // Empty transforms match anything, so find the first non-empty entry as the reference.
276     size_t numKeyframes = m_values.size();
277     size_t firstNonEmptyTransformKeyframeIndex = numKeyframes;
278
279     for (size_t i = 0; i < numKeyframes; ++i) {
280         const TransformAnimationValue* currentKeyframe = static_cast<const TransformAnimationValue*>(m_values.at(i));
281         if (currentKeyframe->value()->size()) {
282             firstNonEmptyTransformKeyframeIndex = i;
283             break;
284         }
285     }
286
287     if (firstNonEmptyTransformKeyframeIndex == numKeyframes)
288         return;
289
290     const TransformOperations* firstVal = static_cast<const TransformAnimationValue*>(m_values.at(firstNonEmptyTransformKeyframeIndex))->value();
291
292     // See if the keyframes are valid.
293     for (size_t i = firstNonEmptyTransformKeyframeIndex + 1; i < numKeyframes; ++i) {
294         const TransformAnimationValue* currentKeyframe = static_cast<const TransformAnimationValue*>(m_values.at(i));
295         const TransformOperations* val = currentKeyframe->value();
296
297         // A null transform matches anything.
298         if (val->operations().isEmpty())
299             continue;
300
301         // If the sizes of the function lists don't match, the lists don't match.
302         if (firstVal->operations().size() != val->operations().size())
303             return;
304
305         // If the types of each function are not the same, the lists don't match.
306         for (size_t j = 0; j < firstVal->operations().size(); ++j) {
307             if (!firstVal->operations()[j]->isSameType(*val->operations()[j]))
308                 return;
309         }
310     }
311
312     // Keyframes are valid.
313     m_transformFunctionListValid = true;
314 }
315
316 }