mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-02-08 01:31:00 +00:00
228 lines
9.5 KiB
Java
Executable File
228 lines
9.5 KiB
Java
Executable File
/*
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.nineoldandroids.animation;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
|
|
import android.view.animation.Interpolator;
|
|
|
|
import com.nineoldandroids.animation.Keyframe.FloatKeyframe;
|
|
import com.nineoldandroids.animation.Keyframe.IntKeyframe;
|
|
import com.nineoldandroids.animation.Keyframe.ObjectKeyframe;
|
|
|
|
/**
|
|
* This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate
|
|
* values between those keyframes for a given animation. The class internal to the animation
|
|
* package because it is an implementation detail of how Keyframes are stored and used.
|
|
*/
|
|
class KeyframeSet {
|
|
|
|
int mNumKeyframes;
|
|
|
|
Keyframe mFirstKeyframe;
|
|
Keyframe mLastKeyframe;
|
|
/*Time*/Interpolator mInterpolator; // only used in the 2-keyframe case
|
|
ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes
|
|
TypeEvaluator mEvaluator;
|
|
|
|
|
|
public KeyframeSet(Keyframe... keyframes) {
|
|
mNumKeyframes = keyframes.length;
|
|
mKeyframes = new ArrayList<Keyframe>();
|
|
mKeyframes.addAll(Arrays.asList(keyframes));
|
|
mFirstKeyframe = mKeyframes.get(0);
|
|
mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
|
|
mInterpolator = mLastKeyframe.getInterpolator();
|
|
}
|
|
|
|
public static KeyframeSet ofInt(int... values) {
|
|
int numKeyframes = values.length;
|
|
IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];
|
|
if (numKeyframes == 1) {
|
|
keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f);
|
|
keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]);
|
|
} else {
|
|
keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]);
|
|
for (int i = 1; i < numKeyframes; ++i) {
|
|
keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);
|
|
}
|
|
}
|
|
return new IntKeyframeSet(keyframes);
|
|
}
|
|
|
|
public static KeyframeSet ofFloat(float... values) {
|
|
int numKeyframes = values.length;
|
|
FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
|
|
if (numKeyframes == 1) {
|
|
keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
|
|
keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
|
|
} else {
|
|
keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
|
|
for (int i = 1; i < numKeyframes; ++i) {
|
|
keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
|
|
}
|
|
}
|
|
return new FloatKeyframeSet(keyframes);
|
|
}
|
|
|
|
public static KeyframeSet ofKeyframe(Keyframe... keyframes) {
|
|
// if all keyframes of same primitive type, create the appropriate KeyframeSet
|
|
int numKeyframes = keyframes.length;
|
|
boolean hasFloat = false;
|
|
boolean hasInt = false;
|
|
boolean hasOther = false;
|
|
for (int i = 0; i < numKeyframes; ++i) {
|
|
if (keyframes[i] instanceof FloatKeyframe) {
|
|
hasFloat = true;
|
|
} else if (keyframes[i] instanceof IntKeyframe) {
|
|
hasInt = true;
|
|
} else {
|
|
hasOther = true;
|
|
}
|
|
}
|
|
if (hasFloat && !hasInt && !hasOther) {
|
|
FloatKeyframe floatKeyframes[] = new FloatKeyframe[numKeyframes];
|
|
for (int i = 0; i < numKeyframes; ++i) {
|
|
floatKeyframes[i] = (FloatKeyframe) keyframes[i];
|
|
}
|
|
return new FloatKeyframeSet(floatKeyframes);
|
|
} else if (hasInt && !hasFloat && !hasOther) {
|
|
IntKeyframe intKeyframes[] = new IntKeyframe[numKeyframes];
|
|
for (int i = 0; i < numKeyframes; ++i) {
|
|
intKeyframes[i] = (IntKeyframe) keyframes[i];
|
|
}
|
|
return new IntKeyframeSet(intKeyframes);
|
|
} else {
|
|
return new KeyframeSet(keyframes);
|
|
}
|
|
}
|
|
|
|
public static KeyframeSet ofObject(Object... values) {
|
|
int numKeyframes = values.length;
|
|
ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)];
|
|
if (numKeyframes == 1) {
|
|
keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f);
|
|
keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]);
|
|
} else {
|
|
keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]);
|
|
for (int i = 1; i < numKeyframes; ++i) {
|
|
keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i / (numKeyframes - 1), values[i]);
|
|
}
|
|
}
|
|
return new KeyframeSet(keyframes);
|
|
}
|
|
|
|
/**
|
|
* Sets the TypeEvaluator to be used when calculating animated values. This object
|
|
* is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet,
|
|
* both of which assume their own evaluator to speed up calculations with those primitive
|
|
* types.
|
|
*
|
|
* @param evaluator The TypeEvaluator to be used to calculate animated values.
|
|
*/
|
|
public void setEvaluator(TypeEvaluator evaluator) {
|
|
mEvaluator = evaluator;
|
|
}
|
|
|
|
@Override
|
|
public KeyframeSet clone() {
|
|
ArrayList<Keyframe> keyframes = mKeyframes;
|
|
int numKeyframes = mKeyframes.size();
|
|
Keyframe[] newKeyframes = new Keyframe[numKeyframes];
|
|
for (int i = 0; i < numKeyframes; ++i) {
|
|
newKeyframes[i] = keyframes.get(i).clone();
|
|
}
|
|
KeyframeSet newSet = new KeyframeSet(newKeyframes);
|
|
return newSet;
|
|
}
|
|
|
|
/**
|
|
* Gets the animated value, given the elapsed fraction of the animation (interpolated by the
|
|
* animation's interpolator) and the evaluator used to calculate in-between values. This
|
|
* function maps the input fraction to the appropriate keyframe interval and a fraction
|
|
* between them and returns the interpolated value. Note that the input fraction may fall
|
|
* outside the [0-1] bounds, if the animation's interpolator made that happen (e.g., a
|
|
* spring interpolation that might send the fraction past 1.0). We handle this situation by
|
|
* just using the two keyframes at the appropriate end when the value is outside those bounds.
|
|
*
|
|
* @param fraction The elapsed fraction of the animation
|
|
* @return The animated value.
|
|
*/
|
|
public Object getValue(float fraction) {
|
|
|
|
// Special-case optimization for the common case of only two keyframes
|
|
if (mNumKeyframes == 2) {
|
|
if (mInterpolator != null) {
|
|
fraction = mInterpolator.getInterpolation(fraction);
|
|
}
|
|
return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(),
|
|
mLastKeyframe.getValue());
|
|
}
|
|
if (fraction <= 0f) {
|
|
final Keyframe nextKeyframe = mKeyframes.get(1);
|
|
final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
|
|
if (interpolator != null) {
|
|
fraction = interpolator.getInterpolation(fraction);
|
|
}
|
|
final float prevFraction = mFirstKeyframe.getFraction();
|
|
float intervalFraction = (fraction - prevFraction) /
|
|
(nextKeyframe.getFraction() - prevFraction);
|
|
return mEvaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(),
|
|
nextKeyframe.getValue());
|
|
} else if (fraction >= 1f) {
|
|
final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2);
|
|
final /*Time*/Interpolator interpolator = mLastKeyframe.getInterpolator();
|
|
if (interpolator != null) {
|
|
fraction = interpolator.getInterpolation(fraction);
|
|
}
|
|
final float prevFraction = prevKeyframe.getFraction();
|
|
float intervalFraction = (fraction - prevFraction) /
|
|
(mLastKeyframe.getFraction() - prevFraction);
|
|
return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
|
|
mLastKeyframe.getValue());
|
|
}
|
|
Keyframe prevKeyframe = mFirstKeyframe;
|
|
for (int i = 1; i < mNumKeyframes; ++i) {
|
|
Keyframe nextKeyframe = mKeyframes.get(i);
|
|
if (fraction < nextKeyframe.getFraction()) {
|
|
final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
|
|
if (interpolator != null) {
|
|
fraction = interpolator.getInterpolation(fraction);
|
|
}
|
|
final float prevFraction = prevKeyframe.getFraction();
|
|
float intervalFraction = (fraction - prevFraction) /
|
|
(nextKeyframe.getFraction() - prevFraction);
|
|
return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
|
|
nextKeyframe.getValue());
|
|
}
|
|
prevKeyframe = nextKeyframe;
|
|
}
|
|
// shouldn't reach here
|
|
return mLastKeyframe.getValue();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
String returnVal = " ";
|
|
for (int i = 0; i < mNumKeyframes; ++i) {
|
|
returnVal += mKeyframes.get(i).getValue() + " ";
|
|
}
|
|
return returnVal;
|
|
}
|
|
}
|