1984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount/* 2984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Copyright (C) 2014 The Android Open Source Project 3984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * 4984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Licensed under the Apache License, Version 2.0 (the "License"); 5984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * you may not use this file except in compliance with the License. 6984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * You may obtain a copy of the License at 7984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * 8984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * http://www.apache.org/licenses/LICENSE-2.0 9984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * 10984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Unless required by applicable law or agreed to in writing, software 11984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * distributed under the License is distributed on an "AS IS" BASIS, 12984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * See the License for the specific language governing permissions and 14984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * limitations under the License. 15984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 16984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mountpackage android.animation; 17984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 18984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mountimport android.graphics.Path; 19984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mountimport android.graphics.PointF; 20984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 21984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mountimport java.util.ArrayList; 22984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 23984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount/** 24984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * PathKeyframes relies on approximating the Path as a series of line segments. 25984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * The line segments are recursively divided until there is less than 1/2 pixel error 26984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * between the lines and the curve. Each point of the line segment is converted 27984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * to a Keyframe and a linear interpolation between Keyframes creates a good approximation 28984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * of the curve. 29984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <p> 30984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * PathKeyframes is optimized to reduce the number of objects created when there are 31984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * many keyframes for a curve. 32984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * </p> 33984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * <p> 34984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Typically, the returned type is a PointF, but the individual components can be extracted 35984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * as either an IntKeyframes or FloatKeyframes. 36984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * </p> 37787e9dd6c81a2db27cd002ca6672be4279cabe88Jorim Jaggi * @hide 38984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 39787e9dd6c81a2db27cd002ca6672be4279cabe88Jorim Jaggipublic class PathKeyframes implements Keyframes { 40984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static final int FRACTION_OFFSET = 0; 41984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static final int X_OFFSET = 1; 42984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static final int Y_OFFSET = 2; 43984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static final int NUM_COMPONENTS = 3; 44984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static final ArrayList<Keyframe> EMPTY_KEYFRAMES = new ArrayList<Keyframe>(); 45984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 46984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private PointF mTempPointF = new PointF(); 47984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private float[] mKeyframeData; 48984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 49984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public PathKeyframes(Path path) { 50984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount this(path, 0.5f); 51984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 52984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 53984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public PathKeyframes(Path path, float error) { 54984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (path == null || path.isEmpty()) { 55984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount throw new IllegalArgumentException("The path must not be null or empty"); 56984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 57984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mKeyframeData = path.approximate(error); 58984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 59984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 60984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 61984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public ArrayList<Keyframe> getKeyframes() { 62984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return EMPTY_KEYFRAMES; 63984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 64984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 65984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 66984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Object getValue(float fraction) { 67984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int numPoints = mKeyframeData.length / 3; 68bc68f5adc222e6438588537fba222ea6a13f46e0George Mount if (fraction < 0) { 69bc68f5adc222e6438588537fba222ea6a13f46e0George Mount return interpolateInRange(fraction, 0, 1); 70bc68f5adc222e6438588537fba222ea6a13f46e0George Mount } else if (fraction > 1) { 71bc68f5adc222e6438588537fba222ea6a13f46e0George Mount return interpolateInRange(fraction, numPoints - 2, numPoints - 1); 72bc68f5adc222e6438588537fba222ea6a13f46e0George Mount } else if (fraction == 0) { 73984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pointForIndex(0); 74984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else if (fraction == 1) { 75984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pointForIndex(numPoints - 1); 76984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else { 77984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount // Binary search for the correct section 78984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int low = 0; 79984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int high = numPoints - 1; 80984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 81984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount while (low <= high) { 82984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int mid = (low + high) / 2; 83984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount float midFraction = mKeyframeData[(mid * NUM_COMPONENTS) + FRACTION_OFFSET]; 84984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 85984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount if (fraction < midFraction) { 86984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount high = mid - 1; 87984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else if (fraction > midFraction) { 88984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount low = mid + 1; 89984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } else { 90984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pointForIndex(mid); 91984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 92984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 93984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 94984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount // now high is below the fraction and low is above the fraction 95bc68f5adc222e6438588537fba222ea6a13f46e0George Mount return interpolateInRange(fraction, high, low); 96bc68f5adc222e6438588537fba222ea6a13f46e0George Mount } 97bc68f5adc222e6438588537fba222ea6a13f46e0George Mount } 98984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 99bc68f5adc222e6438588537fba222ea6a13f46e0George Mount private PointF interpolateInRange(float fraction, int startIndex, int endIndex) { 100bc68f5adc222e6438588537fba222ea6a13f46e0George Mount int startBase = (startIndex * NUM_COMPONENTS); 101bc68f5adc222e6438588537fba222ea6a13f46e0George Mount int endBase = (endIndex * NUM_COMPONENTS); 102984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 103bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float startFraction = mKeyframeData[startBase + FRACTION_OFFSET]; 104bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float endFraction = mKeyframeData[endBase + FRACTION_OFFSET]; 105984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 106bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float intervalFraction = (fraction - startFraction)/(endFraction - startFraction); 107984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 108bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float startX = mKeyframeData[startBase + X_OFFSET]; 109bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float endX = mKeyframeData[endBase + X_OFFSET]; 110bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float startY = mKeyframeData[startBase + Y_OFFSET]; 111bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float endY = mKeyframeData[endBase + Y_OFFSET]; 112984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 113bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float x = interpolate(intervalFraction, startX, endX); 114bc68f5adc222e6438588537fba222ea6a13f46e0George Mount float y = interpolate(intervalFraction, startY, endY); 115bc68f5adc222e6438588537fba222ea6a13f46e0George Mount 116bc68f5adc222e6438588537fba222ea6a13f46e0George Mount mTempPointF.set(x, y); 117bc68f5adc222e6438588537fba222ea6a13f46e0George Mount return mTempPointF; 118984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 119984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 120984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 121984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public void setEvaluator(TypeEvaluator evaluator) { 122984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 123984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 124984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 125984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Class getType() { 126984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return PointF.class; 127984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 128984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 129984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 130984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Keyframes clone() { 131984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes clone = null; 132984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount try { 133984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount clone = (Keyframes) super.clone(); 134984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } catch (CloneNotSupportedException e) {} 135984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return clone; 136984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 137984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 138984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private PointF pointForIndex(int index) { 139984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int base = (index * NUM_COMPONENTS); 140984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int xOffset = base + X_OFFSET; 141984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount int yOffset = base + Y_OFFSET; 142984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount mTempPointF.set(mKeyframeData[xOffset], mKeyframeData[yOffset]); 143984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return mTempPointF; 144984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 145984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 146984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private static float interpolate(float fraction, float startValue, float endValue) { 147984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount float diff = endValue - startValue; 148984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return startValue + (diff * fraction); 149984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 150984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 151984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount /** 152984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Returns a FloatKeyframes for the X component of the Path. 153984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * @return a FloatKeyframes for the X component of the Path. 154984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 155984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public FloatKeyframes createXFloatKeyframes() { 156984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new FloatKeyframesBase() { 157984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 158984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public float getFloatValue(float fraction) { 159984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); 160984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pointF.x; 161984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 162984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount }; 163984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 164984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 165984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount /** 166984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Returns a FloatKeyframes for the Y component of the Path. 167984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * @return a FloatKeyframes for the Y component of the Path. 168984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 169984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public FloatKeyframes createYFloatKeyframes() { 170984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new FloatKeyframesBase() { 171984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 172984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public float getFloatValue(float fraction) { 173984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); 174984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return pointF.y; 175984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 176984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount }; 177984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 178984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 179984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount /** 180984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Returns an IntKeyframes for the X component of the Path. 181984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * @return an IntKeyframes for the X component of the Path. 182984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 183984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public IntKeyframes createXIntKeyframes() { 184984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new IntKeyframesBase() { 185984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 186984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public int getIntValue(float fraction) { 187984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); 188984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return Math.round(pointF.x); 189984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 190984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount }; 191984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 192984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 193984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount /** 194984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * Returns an IntKeyframeSet for the Y component of the Path. 195984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount * @return an IntKeyframeSet for the Y component of the Path. 196984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount */ 197984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public IntKeyframes createYIntKeyframes() { 198984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return new IntKeyframesBase() { 199984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 200984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public int getIntValue(float fraction) { 201984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount PointF pointF = (PointF) PathKeyframes.this.getValue(fraction); 202984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return Math.round(pointF.y); 203984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 204984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount }; 205984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 206984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 207984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount private abstract static class SimpleKeyframes implements Keyframes { 208984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 209984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public void setEvaluator(TypeEvaluator evaluator) { 210984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 211984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 212984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 213984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public ArrayList<Keyframe> getKeyframes() { 214984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return EMPTY_KEYFRAMES; 215984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 216984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 217984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 218984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Keyframes clone() { 219984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount Keyframes clone = null; 220984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount try { 221984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount clone = (Keyframes) super.clone(); 222984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } catch (CloneNotSupportedException e) {} 223984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return clone; 224984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 225984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 226984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 227766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes { 228984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 229984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Class getType() { 230984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return Integer.class; 231984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 232984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 233984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 234984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Object getValue(float fraction) { 235984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return getIntValue(fraction); 236984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 237984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 238984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 239766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu abstract static class FloatKeyframesBase extends SimpleKeyframes 240984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount implements FloatKeyframes { 241984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 242984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Class getType() { 243984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return Float.class; 244984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 245984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount 246984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount @Override 247984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount public Object getValue(float fraction) { 248984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount return getFloatValue(fraction); 249984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 250984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount } 251984011f6850fd4b6ad4db6d6022bd475d7a2c712George Mount} 252