RenderNodeAnimator.java revision 315c329544d7c593d1072b071cbb92d9afe74021
1/*
2 * Copyright (C) 2014 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.view;
18
19import android.animation.TimeInterpolator;
20import android.graphics.Canvas;
21import android.graphics.CanvasProperty;
22import android.graphics.Paint;
23import android.util.SparseIntArray;
24import android.util.TimeUtils;
25
26import com.android.internal.util.VirtualRefBasePtr;
27import com.android.internal.view.animation.FallbackLUTInterpolator;
28import com.android.internal.view.animation.HasNativeInterpolator;
29import com.android.internal.view.animation.NativeInterpolatorFactory;
30
31import java.lang.ref.WeakReference;
32
33/**
34 * @hide
35 */
36public final class RenderNodeAnimator {
37
38    // Keep in sync with enum RenderProperty in Animator.h
39    public static final int TRANSLATION_X = 0;
40    public static final int TRANSLATION_Y = 1;
41    public static final int TRANSLATION_Z = 2;
42    public static final int SCALE_X = 3;
43    public static final int SCALE_Y = 4;
44    public static final int ROTATION = 5;
45    public static final int ROTATION_X = 6;
46    public static final int ROTATION_Y = 7;
47    public static final int X = 8;
48    public static final int Y = 9;
49    public static final int Z = 10;
50    public static final int ALPHA = 11;
51
52    // Keep in sync with enum PaintFields in Animator.h
53    public static final int PAINT_STROKE_WIDTH = 0;
54    public static final int PAINT_ALPHA = 1;
55
56    // ViewPropertyAnimator uses a mask for its values, we need to remap them
57    // to the enum values here. RenderPropertyAnimator can't use the mask values
58    // directly as internally it uses a lookup table so it needs the values to
59    // be sequential starting from 0
60    private static final SparseIntArray sViewPropertyAnimatorMap = new SparseIntArray(15) {{
61        put(ViewPropertyAnimator.TRANSLATION_X, TRANSLATION_X);
62        put(ViewPropertyAnimator.TRANSLATION_Y, TRANSLATION_Y);
63        put(ViewPropertyAnimator.TRANSLATION_Z, TRANSLATION_Z);
64        put(ViewPropertyAnimator.SCALE_X, SCALE_X);
65        put(ViewPropertyAnimator.SCALE_Y, SCALE_Y);
66        put(ViewPropertyAnimator.ROTATION, ROTATION);
67        put(ViewPropertyAnimator.ROTATION_X, ROTATION_X);
68        put(ViewPropertyAnimator.ROTATION_Y, ROTATION_Y);
69        put(ViewPropertyAnimator.X, X);
70        put(ViewPropertyAnimator.Y, Y);
71        put(ViewPropertyAnimator.Z, Z);
72        put(ViewPropertyAnimator.ALPHA, ALPHA);
73    }};
74
75    // Keep in sync DeltaValueType in Animator.h
76    public static final int DELTA_TYPE_ABSOLUTE = 0;
77    public static final int DELTA_TYPE_DELTA = 1;
78
79    private VirtualRefBasePtr mNativePtr;
80
81    private RenderNode mTarget;
82    private TimeInterpolator mInterpolator;
83    private boolean mStarted = false;
84
85    public int mapViewPropertyToRenderProperty(int viewProperty) {
86        return sViewPropertyAnimatorMap.get(viewProperty);
87    }
88
89    public RenderNodeAnimator(int property, int deltaType, float deltaValue) {
90        init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
91                property, deltaType, deltaValue));
92    }
93
94    public RenderNodeAnimator(CanvasProperty<Float> property, int deltaType, float deltaValue) {
95        init(nCreateCanvasPropertyFloatAnimator(
96                new WeakReference<RenderNodeAnimator>(this),
97                property.getNativeContainer(), deltaType, deltaValue));
98    }
99
100    public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField,
101            int deltaType, float deltaValue) {
102        init(nCreateCanvasPropertyPaintAnimator(
103                new WeakReference<RenderNodeAnimator>(this),
104                property.getNativeContainer(), paintField, deltaType, deltaValue));
105    }
106
107    private void init(long ptr) {
108        mNativePtr = new VirtualRefBasePtr(ptr);
109    }
110
111    private void checkMutable() {
112        if (mStarted) {
113            throw new IllegalStateException("Animator has already started, cannot change it now!");
114        }
115    }
116
117    private void applyInterpolator() {
118        if (mInterpolator == null) return;
119
120        long ni;
121        if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) {
122            ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator();
123        } else {
124            int duration = nGetDuration(mNativePtr.get());
125            ni = FallbackLUTInterpolator.createNativeInterpolator(mInterpolator, duration);
126        }
127        nSetInterpolator(mNativePtr.get(), ni);
128    }
129
130    private void start(RenderNode node) {
131        if (mStarted) {
132            throw new IllegalStateException("Already started!");
133        }
134        mStarted = true;
135        applyInterpolator();
136        mTarget = node;
137        mTarget.addAnimator(this);
138    }
139
140    public void start(View target) {
141        start(target.mRenderNode);
142        // Kick off a frame to start the process
143        target.invalidateViewProperty(true, false);
144    }
145
146    public void start(Canvas canvas) {
147        if (!(canvas instanceof GLES20RecordingCanvas)) {
148            throw new IllegalArgumentException("Not a GLES20RecordingCanvas");
149        }
150        GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas;
151        start(recordingCanvas.mNode);
152    }
153
154    public void cancel() {
155        mTarget.removeAnimator(this);
156    }
157
158    public void setDuration(int duration) {
159        checkMutable();
160        nSetDuration(mNativePtr.get(), duration);
161    }
162
163    public void setInterpolator(TimeInterpolator interpolator) {
164        checkMutable();
165        mInterpolator = interpolator;
166    }
167
168    long getNativeAnimator() {
169        return mNativePtr.get();
170    }
171
172    private void onFinished() {
173        mTarget.removeAnimator(this);
174    }
175
176    // Called by native
177    private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) {
178        RenderNodeAnimator animator = weakThis.get();
179        if (animator != null) {
180            animator.onFinished();
181        }
182    }
183
184    private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
185            int property, int deltaValueType, float deltaValue);
186    private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis,
187            long canvasProperty, int deltaValueType, float deltaValue);
188    private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis,
189            long canvasProperty, int paintField, int deltaValueType, float deltaValue);
190    private static native void nSetDuration(long nativePtr, int duration);
191    private static native int nGetDuration(long nativePtr);
192    private static native void nSetInterpolator(long animPtr, long interpolatorPtr);
193}
194