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 
17 package org.mozilla.gecko.animation;
18 
19 import android.view.animation.Animation;
20 import android.view.animation.Transformation;
21 
22 import android.graphics.Camera;
23 import android.graphics.Matrix;
24 
25 /**
26  * An animation that rotates the view on the Y axis between two specified angles.
27  * This animation also adds a translation on the Z axis (depth) to improve the effect.
28  */
29 public class Rotate3DAnimation extends Animation {
30     private final float mFromDegrees;
31     private final float mToDegrees;
32 
33     private final float mCenterX;
34     private final float mCenterY;
35 
36     private final float mDepthZ;
37     private final boolean mReverse;
38     private Camera mCamera;
39 
40     private int mWidth = 1;
41     private int mHeight = 1;
42 
43     /**
44      * Creates a new 3D rotation on the Y axis. The rotation is defined by its
45      * start angle and its end angle. Both angles are in degrees. The rotation
46      * is performed around a center point on the 2D space, defined by a pair
47      * of X and Y coordinates, called centerX and centerY. When the animation
48      * starts, a translation on the Z axis (depth) is performed. The length
49      * of the translation can be specified, as well as whether the translation
50      * should be reversed in time.
51      *
52      * @param fromDegrees the start angle of the 3D rotation
53      * @param toDegrees the end angle of the 3D rotation
54      * @param centerX the X center of the 3D rotation
55      * @param centerY the Y center of the 3D rotation
56      * @param reverse true if the translation should be reversed, false otherwise
57      */
Rotate3DAnimation(float fromDegrees, float toDegrees, float centerX, float centerY, float depthZ, boolean reverse)58     public Rotate3DAnimation(float fromDegrees, float toDegrees,
59             float centerX, float centerY, float depthZ, boolean reverse) {
60         mFromDegrees = fromDegrees;
61         mToDegrees = toDegrees;
62         mCenterX = centerX;
63         mCenterY = centerY;
64         mDepthZ = depthZ;
65         mReverse = reverse;
66     }
67 
68    @Override
initialize(int width, int height, int parentWidth, int parentHeight)69     public void initialize(int width, int height, int parentWidth, int parentHeight) {
70         super.initialize(width, height, parentWidth, parentHeight);
71         mCamera = new Camera();
72         mWidth = width;
73         mHeight = height;
74     }
75 
76     @Override
applyTransformation(float interpolatedTime, Transformation t)77     protected void applyTransformation(float interpolatedTime, Transformation t) {
78         final float fromDegrees = mFromDegrees;
79         float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
80 
81         final Camera camera = mCamera;
82         final Matrix matrix = t.getMatrix();
83 
84         camera.save();
85         if (mReverse) {
86             camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
87         } else {
88             camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
89         }
90         camera.rotateX(degrees);
91         camera.getMatrix(matrix);
92         camera.restore();
93 
94         matrix.preTranslate(-mCenterX * mWidth, -mCenterY * mHeight);
95         matrix.postTranslate(mCenterX * mWidth, mCenterY * mHeight);
96     }
97 }
98