1315c329544d7c593d1072b071cbb92d9afe74021John Reck/*
2315c329544d7c593d1072b071cbb92d9afe74021John Reck * Copyright (C) 2014 The Android Open Source Project
3315c329544d7c593d1072b071cbb92d9afe74021John Reck *
4315c329544d7c593d1072b071cbb92d9afe74021John Reck * Licensed under the Apache License, Version 2.0 (the "License");
5315c329544d7c593d1072b071cbb92d9afe74021John Reck * you may not use this file except in compliance with the License.
6315c329544d7c593d1072b071cbb92d9afe74021John Reck * You may obtain a copy of the License at
7315c329544d7c593d1072b071cbb92d9afe74021John Reck *
8315c329544d7c593d1072b071cbb92d9afe74021John Reck *      http://www.apache.org/licenses/LICENSE-2.0
9315c329544d7c593d1072b071cbb92d9afe74021John Reck *
10315c329544d7c593d1072b071cbb92d9afe74021John Reck * Unless required by applicable law or agreed to in writing, software
11315c329544d7c593d1072b071cbb92d9afe74021John Reck * distributed under the License is distributed on an "AS IS" BASIS,
12315c329544d7c593d1072b071cbb92d9afe74021John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13315c329544d7c593d1072b071cbb92d9afe74021John Reck * See the License for the specific language governing permissions and
14315c329544d7c593d1072b071cbb92d9afe74021John Reck * limitations under the License.
15315c329544d7c593d1072b071cbb92d9afe74021John Reck */
16315c329544d7c593d1072b071cbb92d9afe74021John Reck
17315c329544d7c593d1072b071cbb92d9afe74021John Reckpackage com.android.internal.view.animation;
18315c329544d7c593d1072b071cbb92d9afe74021John Reck
19315c329544d7c593d1072b071cbb92d9afe74021John Reckimport android.animation.TimeInterpolator;
20315c329544d7c593d1072b071cbb92d9afe74021John Reckimport android.util.TimeUtils;
21315c329544d7c593d1072b071cbb92d9afe74021John Reckimport android.view.Choreographer;
22315c329544d7c593d1072b071cbb92d9afe74021John Reck
23315c329544d7c593d1072b071cbb92d9afe74021John Reck/**
24315c329544d7c593d1072b071cbb92d9afe74021John Reck * Interpolator that builds a lookup table to use. This is a fallback for
25315c329544d7c593d1072b071cbb92d9afe74021John Reck * building a native interpolator from a TimeInterpolator that is not marked
26315c329544d7c593d1072b071cbb92d9afe74021John Reck * with {@link HasNativeInterpolator}
27918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck *
28918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck * This implements TimeInterpolator to allow for easier interop with Animators
29315c329544d7c593d1072b071cbb92d9afe74021John Reck */
30315c329544d7c593d1072b071cbb92d9afe74021John Reck@HasNativeInterpolator
31918988c1ce5af002d41c7ac37f3fa490558b0c90John Reckpublic class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator {
32315c329544d7c593d1072b071cbb92d9afe74021John Reck
33a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu    // If the duration of an animation is more than 300 frames, we cap the sample size to 300.
34a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu    private static final int MAX_SAMPLE_POINTS = 300;
35918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck    private TimeInterpolator mSourceInterpolator;
36315c329544d7c593d1072b071cbb92d9afe74021John Reck    private final float mLut[];
37315c329544d7c593d1072b071cbb92d9afe74021John Reck
38315c329544d7c593d1072b071cbb92d9afe74021John Reck    /**
39315c329544d7c593d1072b071cbb92d9afe74021John Reck     * Used to cache the float[] LUT for use across multiple native
40315c329544d7c593d1072b071cbb92d9afe74021John Reck     * interpolator creation
41315c329544d7c593d1072b071cbb92d9afe74021John Reck     */
42ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) {
43918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck        mSourceInterpolator = interpolator;
44315c329544d7c593d1072b071cbb92d9afe74021John Reck        mLut = createLUT(interpolator, duration);
45315c329544d7c593d1072b071cbb92d9afe74021John Reck    }
46315c329544d7c593d1072b071cbb92d9afe74021John Reck
47ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    private static float[] createLUT(TimeInterpolator interpolator, long duration) {
48315c329544d7c593d1072b071cbb92d9afe74021John Reck        long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
49315c329544d7c593d1072b071cbb92d9afe74021John Reck        int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
50a5dcc6c25d38fe63a15f1b5920c439696726d3daTeng-Hui Zhu        // We need 2 frame values as the minimal.
51a5dcc6c25d38fe63a15f1b5920c439696726d3daTeng-Hui Zhu        int numAnimFrames = Math.max(2, (int) Math.ceil(((double) duration) / animIntervalMs));
52a6b967cfc54408f6ee78ae0e4695eca6efd62e89Doris Liu        numAnimFrames = Math.min(numAnimFrames, MAX_SAMPLE_POINTS);
53315c329544d7c593d1072b071cbb92d9afe74021John Reck        float values[] = new float[numAnimFrames];
54315c329544d7c593d1072b071cbb92d9afe74021John Reck        float lastFrame = numAnimFrames - 1;
55315c329544d7c593d1072b071cbb92d9afe74021John Reck        for (int i = 0; i < numAnimFrames; i++) {
56315c329544d7c593d1072b071cbb92d9afe74021John Reck            float inValue = i / lastFrame;
57315c329544d7c593d1072b071cbb92d9afe74021John Reck            values[i] = interpolator.getInterpolation(inValue);
58315c329544d7c593d1072b071cbb92d9afe74021John Reck        }
59315c329544d7c593d1072b071cbb92d9afe74021John Reck        return values;
60315c329544d7c593d1072b071cbb92d9afe74021John Reck    }
61315c329544d7c593d1072b071cbb92d9afe74021John Reck
62315c329544d7c593d1072b071cbb92d9afe74021John Reck    @Override
63315c329544d7c593d1072b071cbb92d9afe74021John Reck    public long createNativeInterpolator() {
64315c329544d7c593d1072b071cbb92d9afe74021John Reck        return NativeInterpolatorFactoryHelper.createLutInterpolator(mLut);
65315c329544d7c593d1072b071cbb92d9afe74021John Reck    }
66315c329544d7c593d1072b071cbb92d9afe74021John Reck
67315c329544d7c593d1072b071cbb92d9afe74021John Reck    /**
68315c329544d7c593d1072b071cbb92d9afe74021John Reck     * Used to create a one-shot float[] LUT & native interpolator
69315c329544d7c593d1072b071cbb92d9afe74021John Reck     */
70ad2f8e334f3ef22d3e412b0660a2e1f996f94116Alan Viverette    public static long createNativeInterpolator(TimeInterpolator interpolator, long duration) {
71315c329544d7c593d1072b071cbb92d9afe74021John Reck        float[] lut = createLUT(interpolator, duration);
72315c329544d7c593d1072b071cbb92d9afe74021John Reck        return NativeInterpolatorFactoryHelper.createLutInterpolator(lut);
73315c329544d7c593d1072b071cbb92d9afe74021John Reck    }
74918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck
75918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck    @Override
76918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck    public float getInterpolation(float input) {
77918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck        return mSourceInterpolator.getInterpolation(input);
78918988c1ce5af002d41c7ac37f3fa490558b0c90John Reck    }
79315c329544d7c593d1072b071cbb92d9afe74021John Reck}
80