1 /* 2 * Copyright (C) 2024 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 package com.android.internal.widget.remotecompose.core.operations.utilities.easing; 17 18 class CubicEasing extends Easing { 19 float mType = 0; 20 float mX1 = 0f; 21 float mY1 = 0f; 22 float mX2 = 0f; 23 float mY2 = 0f; 24 25 private static final float[] STANDARD = {0.4f, 0.0f, 0.2f, 1f}; 26 private static final float[] ACCELERATE = {0.4f, 0.05f, 0.8f, 0.7f}; 27 private static final float[] DECELERATE = {0.0f, 0.0f, 0.2f, 0.95f}; 28 private static final float[] LINEAR = {1f, 1f, 0f, 0f}; 29 private static final float[] ANTICIPATE = {0.36f, 0f, 0.66f, -0.56f}; 30 private static final float[] OVERSHOOT = {0.34f, 1.56f, 0.64f, 1f}; 31 CubicEasing(int type)32 CubicEasing(int type) { 33 mType = type; 34 config(type); 35 } 36 CubicEasing(float x1, float y1, float x2, float y2)37 CubicEasing(float x1, float y1, float x2, float y2) { 38 setup(x1, y1, x2, y2); 39 } 40 config(int type)41 public void config(int type) { 42 43 switch (type) { 44 case CUBIC_STANDARD: 45 setup(STANDARD); 46 break; 47 case CUBIC_ACCELERATE: 48 setup(ACCELERATE); 49 break; 50 case CUBIC_DECELERATE: 51 setup(DECELERATE); 52 break; 53 case CUBIC_LINEAR: 54 setup(LINEAR); 55 break; 56 case CUBIC_ANTICIPATE: 57 setup(ANTICIPATE); 58 break; 59 case CUBIC_OVERSHOOT: 60 setup(OVERSHOOT); 61 break; 62 } 63 mType = type; 64 } 65 setup(float[] values)66 void setup(float[] values) { 67 setup(values[0], values[1], values[2], values[3]); 68 } 69 setup(float x1, float y1, float x2, float y2)70 void setup(float x1, float y1, float x2, float y2) { 71 mX1 = x1; 72 mY1 = y1; 73 mX2 = x2; 74 mY2 = y2; 75 } 76 getX(float t)77 private float getX(float t) { 78 float t1 = 1 - t; 79 // no need for because start at 0,0 float f0 = (1 - t) * (1 - t) * (1 - t) 80 float f1 = 3 * t1 * t1 * t; 81 float f2 = 3 * t1 * t * t; 82 float f3 = t * t * t; 83 return mX1 * f1 + mX2 * f2 + f3; 84 } 85 getY(float t)86 private float getY(float t) { 87 float t1 = 1 - t; 88 // no need for testing because start at 0,0 float f0 = (1 - t) * (1 - t) * (1 - t) 89 float f1 = 3 * t1 * t1 * t; 90 float f2 = 3 * t1 * t * t; 91 float f3 = t * t * t; 92 return mY1 * f1 + mY2 * f2 + f3; 93 } 94 getDiffX(float t)95 private float getDiffX(float t) { 96 float t1 = 1 - t; 97 return 3 * t1 * t1 * mX1 + 6 * t1 * t * (mX2 - mX1) + 3 * t * t * (1 - mX2); 98 } 99 getDiffY(float t)100 private float getDiffY(float t) { 101 float t1 = 1 - t; 102 return 3 * t1 * t1 * mY1 + 6 * t1 * t * (mY2 - mY1) + 3 * t * t * (1 - mY2); 103 } 104 105 /** 106 * binary search for the region and linear interpolate the answer 107 */ getDiff(float x)108 public float getDiff(float x) { 109 float t = 0.5f; 110 float range = 0.5f; 111 while (range > D_ERROR) { 112 float tx = getX(t); 113 range *= 0.5; 114 if (tx < x) { 115 t += range; 116 } else { 117 t -= range; 118 } 119 } 120 float x1 = getX(t - range); 121 float x2 = getX(t + range); 122 float y1 = getY(t - range); 123 float y2 = getY(t + range); 124 return (y2 - y1) / (x2 - x1); 125 } 126 127 /** 128 * binary search for the region and linear interpolate the answer 129 */ get(float x)130 public float get(float x) { 131 if (x <= 0.0f) { 132 return 0f; 133 } 134 if (x >= 1.0f) { 135 return 1.0f; 136 } 137 float t = 0.5f; 138 float range = 0.5f; 139 while (range > ERROR) { 140 float tx = getX(t); 141 range *= 0.5f; 142 if (tx < x) { 143 t += range; 144 } else { 145 t -= range; 146 } 147 } 148 float x1 = getX(t - range); 149 float x2 = getX(t + range); 150 float y1 = getY(t - range); 151 float y2 = getY(t + range); 152 return (y2 - y1) * (x - x1) / (x2 - x1) + y1; 153 } 154 155 private static final float ERROR = 0.01f; 156 private static final float D_ERROR = 0.0001f; 157 } 158