• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 com.android.dialer.compat;
18 
19 import android.graphics.Path;
20 import android.graphics.PathMeasure;
21 import android.os.Build;
22 import android.view.animation.Interpolator;
23 import android.view.animation.PathInterpolator;
24 
25 public class PathInterpolatorCompat {
26 
create( float controlX1, float controlY1, float controlX2, float controlY2)27   public static Interpolator create(
28       float controlX1, float controlY1, float controlX2, float controlY2) {
29     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
30       return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);
31     }
32     return new PathInterpolatorBase(controlX1, controlY1, controlX2, controlY2);
33   }
34 
35   private static class PathInterpolatorBase implements Interpolator {
36 
37     /** Governs the accuracy of the approximation of the {@link Path}. */
38     private static final float PRECISION = 0.002f;
39 
40     private final float[] mX;
41     private final float[] mY;
42 
PathInterpolatorBase(Path path)43     public PathInterpolatorBase(Path path) {
44       final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);
45 
46       final float pathLength = pathMeasure.getLength();
47       final int numPoints = (int) (pathLength / PRECISION) + 1;
48 
49       mX = new float[numPoints];
50       mY = new float[numPoints];
51 
52       final float[] position = new float[2];
53       for (int i = 0; i < numPoints; ++i) {
54         final float distance = (i * pathLength) / (numPoints - 1);
55         pathMeasure.getPosTan(distance, position, null /* tangent */);
56 
57         mX[i] = position[0];
58         mY[i] = position[1];
59       }
60     }
61 
PathInterpolatorBase(float controlX, float controlY)62     public PathInterpolatorBase(float controlX, float controlY) {
63       this(createQuad(controlX, controlY));
64     }
65 
PathInterpolatorBase( float controlX1, float controlY1, float controlX2, float controlY2)66     public PathInterpolatorBase(
67         float controlX1, float controlY1, float controlX2, float controlY2) {
68       this(createCubic(controlX1, controlY1, controlX2, controlY2));
69     }
70 
createQuad(float controlX, float controlY)71     private static Path createQuad(float controlX, float controlY) {
72       final Path path = new Path();
73       path.moveTo(0.0f, 0.0f);
74       path.quadTo(controlX, controlY, 1.0f, 1.0f);
75       return path;
76     }
77 
createCubic( float controlX1, float controlY1, float controlX2, float controlY2)78     private static Path createCubic(
79         float controlX1, float controlY1, float controlX2, float controlY2) {
80       final Path path = new Path();
81       path.moveTo(0.0f, 0.0f);
82       path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0f, 1.0f);
83       return path;
84     }
85 
86     @Override
getInterpolation(float t)87     public float getInterpolation(float t) {
88       if (t <= 0.0f) {
89         return 0.0f;
90       } else if (t >= 1.0f) {
91         return 1.0f;
92       }
93 
94       // Do a binary search for the correct x to interpolate between.
95       int startIndex = 0;
96       int endIndex = mX.length - 1;
97       while (endIndex - startIndex > 1) {
98         int midIndex = (startIndex + endIndex) / 2;
99         if (t < mX[midIndex]) {
100           endIndex = midIndex;
101         } else {
102           startIndex = midIndex;
103         }
104       }
105 
106       final float xRange = mX[endIndex] - mX[startIndex];
107       if (xRange == 0) {
108         return mY[startIndex];
109       }
110 
111       final float tInRange = t - mX[startIndex];
112       final float fraction = tInRange / xRange;
113 
114       final float startY = mY[startIndex];
115       final float endY = mY[endIndex];
116 
117       return startY + (fraction * (endY - startY));
118     }
119   }
120 }
121