1/*
2 * Copyright (C) 2007 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.graphics;
18
19import android.os.SystemClock;
20
21public class Interpolator {
22
23    public Interpolator(int valueCount) {
24        mValueCount = valueCount;
25        mFrameCount = 2;
26        native_instance = nativeConstructor(valueCount, 2);
27    }
28
29    public Interpolator(int valueCount, int frameCount) {
30        mValueCount = valueCount;
31        mFrameCount = frameCount;
32        native_instance = nativeConstructor(valueCount, frameCount);
33    }
34
35    /**
36     * Reset the Interpolator to have the specified number of values and an
37     * implicit keyFrame count of 2 (just a start and end). After this call the
38     * values for each keyFrame must be assigned using setKeyFrame().
39     */
40    public void reset(int valueCount) {
41        reset(valueCount, 2);
42    }
43
44    /**
45     * Reset the Interpolator to have the specified number of values and
46     * keyFrames. After this call the values for each keyFrame must be assigned
47     * using setKeyFrame().
48     */
49    public void reset(int valueCount, int frameCount) {
50        mValueCount = valueCount;
51        mFrameCount = frameCount;
52        nativeReset(native_instance, valueCount, frameCount);
53    }
54
55    public final int getKeyFrameCount() {
56        return mFrameCount;
57    }
58
59    public final int getValueCount() {
60        return mValueCount;
61    }
62
63    /**
64     * Assign the keyFrame (specified by index) a time value and an array of key
65     * values (with an implicity blend array of [0, 0, 1, 1] giving linear
66     * transition to the next set of key values).
67     *
68     * @param index The index of the key frame to assign
69     * @param msec The time (in mililiseconds) for this key frame. Based on the
70     *        SystemClock.uptimeMillis() clock
71     * @param values Array of values associated with theis key frame
72     */
73    public void setKeyFrame(int index, int msec, float[] values) {
74        setKeyFrame(index, msec, values, null);
75    }
76
77    /**
78     * Assign the keyFrame (specified by index) a time value and an array of key
79     * values and blend array.
80     *
81     * @param index The index of the key frame to assign
82     * @param msec The time (in mililiseconds) for this key frame. Based on the
83     *        SystemClock.uptimeMillis() clock
84     * @param values Array of values associated with theis key frame
85     * @param blend (may be null) Optional array of 4 blend values
86     */
87    public void setKeyFrame(int index, int msec, float[] values, float[] blend) {
88        if (index < 0 || index >= mFrameCount) {
89            throw new IndexOutOfBoundsException();
90        }
91        if (values.length < mValueCount) {
92            throw new ArrayStoreException();
93        }
94        if (blend != null && blend.length < 4) {
95            throw new ArrayStoreException();
96        }
97        nativeSetKeyFrame(native_instance, index, msec, values, blend);
98    }
99
100    /**
101     * Set a repeat count (which may be fractional) for the interpolator, and
102     * whether the interpolator should mirror its repeats. The default settings
103     * are repeatCount = 1, and mirror = false.
104     */
105    public void setRepeatMirror(float repeatCount, boolean mirror) {
106        if (repeatCount >= 0) {
107            nativeSetRepeatMirror(native_instance, repeatCount, mirror);
108        }
109    }
110
111    public enum Result {
112        NORMAL,
113        FREEZE_START,
114        FREEZE_END
115    }
116
117    /**
118     * Calls timeToValues(msec, values) with the msec set to now (by calling
119     * (int)SystemClock.uptimeMillis().)
120     */
121    public Result timeToValues(float[] values) {
122        return timeToValues((int)SystemClock.uptimeMillis(), values);
123    }
124
125    /**
126     * Given a millisecond time value (msec), return the interpolated values and
127     * return whether the specified time was within the range of key times
128     * (NORMAL), was before the first key time (FREEZE_START) or after the last
129     * key time (FREEZE_END). In any event, computed values are always returned.
130     *
131     * @param msec The time (in milliseconds) used to sample into the
132     *        Interpolator. Based on the SystemClock.uptimeMillis() clock
133     * @param values Where to write the computed values (may be NULL).
134     * @return how the values were computed (even if values == null)
135     */
136    public Result timeToValues(int msec, float[] values) {
137        if (values != null && values.length < mValueCount) {
138            throw new ArrayStoreException();
139        }
140        switch (nativeTimeToValues(native_instance, msec, values)) {
141            case 0: return Result.NORMAL;
142            case 1: return Result.FREEZE_START;
143            default: return Result.FREEZE_END;
144        }
145    }
146
147    @Override
148    protected void finalize() throws Throwable {
149        nativeDestructor(native_instance);
150        native_instance = 0;  // Other finalizers can still call us.
151    }
152
153    private int mValueCount;
154    private int mFrameCount;
155    private long native_instance;
156
157    private static native long nativeConstructor(int valueCount, int frameCount);
158    private static native void nativeDestructor(long native_instance);
159    private static native void nativeReset(long native_instance, int valueCount, int frameCount);
160    private static native void nativeSetKeyFrame(long native_instance, int index, int msec, float[] values, float[] blend);
161    private static native void nativeSetRepeatMirror(long native_instance, float repeatCount, boolean mirror);
162    private static native int  nativeTimeToValues(long native_instance, int msec, float[] values);
163}
164
165