1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.animation;
18
19import android.animation.Keyframe.FloatKeyframe;
20
21import java.util.ArrayList;
22import java.util.List;
23
24/**
25 * This class holds a collection of FloatKeyframe objects and is called by ValueAnimator to calculate
26 * values between those keyframes for a given animation. The class internal to the animation
27 * package because it is an implementation detail of how Keyframes are stored and used.
28 *
29 * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for
30 * int, exists to speed up the getValue() method when there is no custom
31 * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the
32 * Object equivalents of these primitive types.</p>
33 */
34class FloatKeyframeSet extends KeyframeSet implements Keyframes.FloatKeyframes {
35    private float firstValue;
36    private float lastValue;
37    private float deltaValue;
38    private boolean firstTime = true;
39
40    public FloatKeyframeSet(FloatKeyframe... keyframes) {
41        super(keyframes);
42    }
43
44    @Override
45    public Object getValue(float fraction) {
46        return getFloatValue(fraction);
47    }
48
49    @Override
50    public FloatKeyframeSet clone() {
51        final List<Keyframe> keyframes = mKeyframes;
52        final int numKeyframes = mKeyframes.size();
53        FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes];
54        for (int i = 0; i < numKeyframes; ++i) {
55            newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone();
56        }
57        FloatKeyframeSet newSet = new FloatKeyframeSet(newKeyframes);
58        return newSet;
59    }
60
61    @Override
62    public void invalidateCache() {
63        firstTime = true;
64    }
65
66    @Override
67    public float getFloatValue(float fraction) {
68        if (mNumKeyframes == 2) {
69            if (firstTime) {
70                firstTime = false;
71                firstValue = ((FloatKeyframe) mKeyframes.get(0)).getFloatValue();
72                lastValue = ((FloatKeyframe) mKeyframes.get(1)).getFloatValue();
73                deltaValue = lastValue - firstValue;
74            }
75            if (mInterpolator != null) {
76                fraction = mInterpolator.getInterpolation(fraction);
77            }
78            if (mEvaluator == null) {
79                return firstValue + fraction * deltaValue;
80            } else {
81                return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).floatValue();
82            }
83        }
84        if (fraction <= 0f) {
85            final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0);
86            final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(1);
87            float prevValue = prevKeyframe.getFloatValue();
88            float nextValue = nextKeyframe.getFloatValue();
89            float prevFraction = prevKeyframe.getFraction();
90            float nextFraction = nextKeyframe.getFraction();
91            final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
92            if (interpolator != null) {
93                fraction = interpolator.getInterpolation(fraction);
94            }
95            float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
96            return mEvaluator == null ?
97                    prevValue + intervalFraction * (nextValue - prevValue) :
98                    ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
99                            floatValue();
100        } else if (fraction >= 1f) {
101            final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 2);
102            final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 1);
103            float prevValue = prevKeyframe.getFloatValue();
104            float nextValue = nextKeyframe.getFloatValue();
105            float prevFraction = prevKeyframe.getFraction();
106            float nextFraction = nextKeyframe.getFraction();
107            final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
108            if (interpolator != null) {
109                fraction = interpolator.getInterpolation(fraction);
110            }
111            float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
112            return mEvaluator == null ?
113                    prevValue + intervalFraction * (nextValue - prevValue) :
114                    ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
115                            floatValue();
116        }
117        FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0);
118        for (int i = 1; i < mNumKeyframes; ++i) {
119            FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i);
120            if (fraction < nextKeyframe.getFraction()) {
121                final TimeInterpolator interpolator = nextKeyframe.getInterpolator();
122                if (interpolator != null) {
123                    fraction = interpolator.getInterpolation(fraction);
124                }
125                float intervalFraction = (fraction - prevKeyframe.getFraction()) /
126                    (nextKeyframe.getFraction() - prevKeyframe.getFraction());
127                float prevValue = prevKeyframe.getFloatValue();
128                float nextValue = nextKeyframe.getFloatValue();
129                return mEvaluator == null ?
130                        prevValue + intervalFraction * (nextValue - prevValue) :
131                        ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
132                            floatValue();
133            }
134            prevKeyframe = nextKeyframe;
135        }
136        // shouldn't get here
137        return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue();
138    }
139
140    @Override
141    public Class getType() {
142        return Float.class;
143    }
144}
145
146