1 /*
2  * Copyright (C) 2006 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 android.view.animation;
18 
19 import android.annotation.FloatRange;
20 import android.compat.annotation.UnsupportedAppUsage;
21 import android.graphics.Insets;
22 import android.graphics.Matrix;
23 import android.graphics.Rect;
24 
25 import java.io.PrintWriter;
26 
27 /**
28  * Defines the transformation to be applied at
29  * one point in time of an Animation.
30  *
31  */
32 public class Transformation {
33     /**
34      * Indicates a transformation that has no effect (alpha = 1 and identity matrix.)
35      */
36     public static final int TYPE_IDENTITY = 0x0;
37     /**
38      * Indicates a transformation that applies an alpha only (uses an identity matrix.)
39      */
40     public static final int TYPE_ALPHA = 0x1;
41     /**
42      * Indicates a transformation that applies a matrix only (alpha = 1.)
43      */
44     public static final int TYPE_MATRIX = 0x2;
45     /**
46      * Indicates a transformation that applies an alpha and a matrix.
47      */
48     public static final int TYPE_BOTH = TYPE_ALPHA | TYPE_MATRIX;
49 
50     protected Matrix mMatrix;
51     protected float mAlpha;
52     protected int mTransformationType;
53 
54     private boolean mHasClipRect;
55     private Rect mClipRect = new Rect();
56 
57     private Insets mInsets = Insets.NONE;
58 
59     /**
60      * Creates a new transformation with alpha = 1 and the identity matrix.
61      */
Transformation()62     public Transformation() {
63         clear();
64     }
65 
66     /**
67      * Reset the transformation to a state that leaves the object
68      * being animated in an unmodified state. The transformation type is
69      * {@link #TYPE_BOTH} by default.
70      */
clear()71     public void clear() {
72         if (mMatrix == null) {
73             mMatrix = new Matrix();
74         } else {
75             mMatrix.reset();
76         }
77         mClipRect.setEmpty();
78         mHasClipRect = false;
79         mAlpha = 1.0f;
80         mTransformationType = TYPE_BOTH;
81         mInsets = Insets.NONE;
82     }
83 
84     /**
85      * Indicates the nature of this transformation.
86      *
87      * @return {@link #TYPE_ALPHA}, {@link #TYPE_MATRIX},
88      *         {@link #TYPE_BOTH} or {@link #TYPE_IDENTITY}.
89      */
getTransformationType()90     public int getTransformationType() {
91         return mTransformationType;
92     }
93 
94     /**
95      * Sets the transformation type.
96      *
97      * @param transformationType One of {@link #TYPE_ALPHA},
98      *        {@link #TYPE_MATRIX}, {@link #TYPE_BOTH} or
99      *        {@link #TYPE_IDENTITY}.
100      */
setTransformationType(int transformationType)101     public void setTransformationType(int transformationType) {
102         mTransformationType = transformationType;
103     }
104 
105     /**
106      * Clones the specified transformation.
107      *
108      * @param t The transformation to clone.
109      */
set(Transformation t)110     public void set(Transformation t) {
111         mAlpha = t.getAlpha();
112         mMatrix.set(t.getMatrix());
113         if (t.mHasClipRect) {
114             setClipRect(t.getClipRect());
115         } else {
116             mHasClipRect = false;
117             mClipRect.setEmpty();
118         }
119         mTransformationType = t.getTransformationType();
120     }
121 
122     /**
123      * Apply this Transformation to an existing Transformation, e.g. apply
124      * a scale effect to something that has already been rotated.
125      * @param t
126      */
compose(Transformation t)127     public void compose(Transformation t) {
128         mAlpha *= t.getAlpha();
129         mMatrix.preConcat(t.getMatrix());
130         if (t.mHasClipRect) {
131             Rect bounds = t.getClipRect();
132             if (mHasClipRect) {
133                 setClipRect(mClipRect.left + bounds.left, mClipRect.top + bounds.top,
134                         mClipRect.right + bounds.right, mClipRect.bottom + bounds.bottom);
135             } else {
136                 setClipRect(bounds);
137             }
138         }
139         setInsets(Insets.add(getInsets(), t.getInsets()));
140     }
141 
142     /**
143      * Like {@link #compose(Transformation)} but does this.postConcat(t) of
144      * the transformation matrix.
145      * @hide
146      */
postCompose(Transformation t)147     public void postCompose(Transformation t) {
148         mAlpha *= t.getAlpha();
149         mMatrix.postConcat(t.getMatrix());
150         if (t.mHasClipRect) {
151             Rect bounds = t.getClipRect();
152             if (mHasClipRect) {
153                 setClipRect(mClipRect.left + bounds.left, mClipRect.top + bounds.top,
154                         mClipRect.right + bounds.right, mClipRect.bottom + bounds.bottom);
155             } else {
156                 setClipRect(bounds);
157             }
158         }
159     }
160 
161     /**
162      * @return The 3x3 Matrix representing the transformation to apply to the
163      * coordinates of the object being animated
164      */
getMatrix()165     public Matrix getMatrix() {
166         return mMatrix;
167     }
168 
169     /**
170      * Sets the degree of transparency
171      * @param alpha 1.0 means fully opaque and 0.0 means fully transparent
172      */
setAlpha(@loatRangefrom=0.0, to=1.0) float alpha)173     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
174         mAlpha = alpha;
175     }
176 
177     /**
178      * @return The degree of transparency
179      */
getAlpha()180     public float getAlpha() {
181         return mAlpha;
182     }
183 
184     /**
185      * Sets the current Transform's clip rect
186      * @hide
187      */
setClipRect(Rect r)188     public void setClipRect(Rect r) {
189         setClipRect(r.left, r.top, r.right, r.bottom);
190     }
191 
192     /**
193      * Sets the current Transform's clip rect
194      * @hide
195      */
setClipRect(int l, int t, int r, int b)196     public void setClipRect(int l, int t, int r, int b) {
197         mClipRect.set(l, t, r, b);
198         mHasClipRect = true;
199     }
200 
201     /**
202      * Returns the current Transform's clip rect
203      * @hide
204      */
getClipRect()205     public Rect getClipRect() {
206         return mClipRect;
207     }
208 
209     /**
210      * Returns whether the current Transform's clip rect is set
211      * @hide
212      */
hasClipRect()213     public boolean hasClipRect() {
214         return mHasClipRect;
215     }
216 
217     /**
218      * Sets the current Transform's insets
219      * @hide
220      */
setInsets(Insets insets)221     public void setInsets(Insets insets) {
222         mInsets = insets;
223     }
224 
225     /**
226      * Sets the current Transform's insets
227      * @hide
228      */
setInsets(int left, int top, int right, int bottom)229     public void setInsets(int left, int top, int right, int bottom) {
230         mInsets = Insets.of(left, top, right, bottom);
231     }
232 
233     /**
234      * Returns the current Transform's outset rect
235      * @hide
236      */
getInsets()237     public Insets getInsets() {
238         return mInsets;
239     }
240 
241     @Override
toString()242     public String toString() {
243         StringBuilder sb = new StringBuilder(64);
244         sb.append("Transformation");
245         toShortString(sb);
246         return sb.toString();
247     }
248 
249     /**
250      * Return a string representation of the transformation in a compact form.
251      */
toShortString()252     public String toShortString() {
253         StringBuilder sb = new StringBuilder(64);
254         toShortString(sb);
255         return sb.toString();
256     }
257 
258     /**
259      * @hide
260      */
toShortString(StringBuilder sb)261     public void toShortString(StringBuilder sb) {
262         sb.append("{alpha="); sb.append(mAlpha);
263         sb.append(" matrix="); sb.append(mMatrix.toShortString());
264         sb.append('}');
265     }
266 
267     /**
268      * Print short string, to optimize dumping.
269      * @hide
270      */
271     @UnsupportedAppUsage
printShortString(PrintWriter pw)272     public void printShortString(PrintWriter pw) {
273         pw.print("{alpha="); pw.print(mAlpha);
274         pw.print(" matrix=");
275         mMatrix.dump(pw);
276         pw.print('}');
277     }
278 }
279