Support Keyframe definition for AVD on RT
BUG: 27441613
Change-Id: Iece386f65f3704d1b7caa2b3690a8d3048ccf6e2
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 3e7cbbd..ba16e67 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -1095,8 +1095,12 @@
}
// TODO: We need a better way to get data out of keyframes.
if (mKeyframes instanceof PathKeyframes.FloatKeyframesBase
- || mKeyframes instanceof PathKeyframes.IntKeyframesBase) {
- // property values will animate based on external data source (e.g. Path)
+ || mKeyframes instanceof PathKeyframes.IntKeyframesBase
+ || (mKeyframes.getKeyframes() != null && mKeyframes.getKeyframes().size() > 2)) {
+ // When a pvh has more than 2 keyframes, that means there are intermediate values in
+ // addition to start/end values defined for animators. Another case where such
+ // intermediate values are defined is when animator has a path to animate along. In
+ // these cases, a data source is needed to capture these intermediate values.
values.dataSource = new PropertyValues.DataSource() {
@Override
public Object getValueAtFraction(float fraction) {
diff --git a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
index 9e2cbdb..d28ab07 100644
--- a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
+++ b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java
@@ -30,6 +30,8 @@
@HasNativeInterpolator
public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator {
+ // If the duration of an animation is more than 300 frames, we cap the sample size to 300.
+ private static final int MAX_SAMPLE_POINTS = 300;
private TimeInterpolator mSourceInterpolator;
private final float mLut[];
@@ -47,6 +49,7 @@
int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
// We need 2 frame values as the minimal.
int numAnimFrames = Math.max(2, (int) Math.ceil(((double) duration) / animIntervalMs));
+ numAnimFrames = Math.min(numAnimFrames, MAX_SAMPLE_POINTS);
float values[] = new float[numAnimFrames];
float lastFrame = numAnimFrames - 1;
for (int i = 0; i < numAnimFrames; i++) {
diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
index 0ba88e6..47252ad 100644
--- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp
@@ -142,14 +142,24 @@
startValue, endValue);
return reinterpret_cast<jlong>(newHolder);
}
-static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr,
+static void setFloatPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr,
jfloatArray srcData, jint length) {
-
jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr);
- PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr);
+ PropertyValuesHolderImpl<float>* holder =
+ reinterpret_cast<PropertyValuesHolderImpl<float>*>(propertyHolderPtr);
holder->setPropertyDataSource(propertyData, length);
env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT);
}
+
+static void setIntPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr,
+ jintArray srcData, jint length) {
+ jint* propertyData = env->GetIntArrayElements(srcData, nullptr);
+ PropertyValuesHolderImpl<int>* holder =
+ reinterpret_cast<PropertyValuesHolderImpl<int>*>(propertyHolderPtr);
+ holder->setPropertyDataSource(propertyData, length);
+ env->ReleaseIntArrayElements(srcData, propertyData, JNI_ABORT);
+}
+
static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) {
PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr);
AnimationListener* listener = createAnimationListener(env, finishListener, id);
@@ -181,7 +191,8 @@
{"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder},
{"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder},
{"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder},
- {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData},
+ {"nSetPropertyHolderData", "(J[FI)V", (void*)setFloatPropertyHolderData},
+ {"nSetPropertyHolderData", "(J[II)V", (void*)setIntPropertyHolderData},
{"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start},
{"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse},
{"nEnd", "!(J)V", (void*)end},
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 3eace30..6bb93aec 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -1041,6 +1041,9 @@
private static final int REVERSE_ANIMATION = 2;
private static final int RESET_ANIMATION = 3;
private static final int END_ANIMATION = 4;
+
+ // If the duration of an animation is more than 300 frames, we cap the sample size to 300.
+ private static final int MAX_SAMPLE_POINTS = 300;
private AnimatorListener mListener = null;
private final LongArray mStartDelays = new LongArray();
private PropertyValuesHolder.PropertyValues mTmpValues =
@@ -1180,8 +1183,8 @@
long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId,
(Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
if (mTmpValues.dataSource != null) {
- float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
- .getDuration());
+ float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
+ animator.getDuration());
nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
}
createNativeChildAnimator(propertyPtr, startTime, animator);
@@ -1217,10 +1220,22 @@
}
propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId,
(Float) mTmpValues.startValue, (Float) mTmpValues.endValue);
+ if (mTmpValues.dataSource != null) {
+ // Pass keyframe data to native, if any.
+ float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
+ animator.getDuration());
+ nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
+ }
} else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) {
propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId,
(Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue);
+ if (mTmpValues.dataSource != null) {
+ // Pass keyframe data to native, if any.
+ int[] dataPoints = createIntDataPoints(mTmpValues.dataSource,
+ animator.getDuration());
+ nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
+ }
} else {
if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
return;
@@ -1230,45 +1245,63 @@
"supported for Paths.");
}
}
- if (mTmpValues.dataSource != null) {
- float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator
- .getDuration());
- nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
- }
createNativeChildAnimator(propertyPtr, startTime, animator);
}
private void createRTAnimatorForRootGroup(PropertyValuesHolder[] values,
ObjectAnimator animator, VectorDrawable.VectorDrawableState target,
long startTime) {
- long nativePtr = target.getNativeRenderer();
- if (!animator.getPropertyName().equals("alpha")) {
- if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
- return;
- } else {
- throw new UnsupportedOperationException("Only alpha is supported for root "
- + "group");
- }
+ long nativePtr = target.getNativeRenderer();
+ if (!animator.getPropertyName().equals("alpha")) {
+ if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
+ return;
+ } else {
+ throw new UnsupportedOperationException("Only alpha is supported for root "
+ + "group");
}
- Float startValue = null;
- Float endValue = null;
- for (int i = 0; i < values.length; i++) {
- values[i].getPropertyValues(mTmpValues);
- if (mTmpValues.propertyName.equals("alpha")) {
- startValue = (Float) mTmpValues.startValue;
- endValue = (Float) mTmpValues.endValue;
- break;
- }
+ }
+ Float startValue = null;
+ Float endValue = null;
+ for (int i = 0; i < values.length; i++) {
+ values[i].getPropertyValues(mTmpValues);
+ if (mTmpValues.propertyName.equals("alpha")) {
+ startValue = (Float) mTmpValues.startValue;
+ endValue = (Float) mTmpValues.endValue;
+ break;
}
- if (startValue == null && endValue == null) {
- if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
- return;
- } else {
- throw new UnsupportedOperationException("No alpha values are specified");
- }
+ }
+ if (startValue == null && endValue == null) {
+ if (mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
+ return;
+ } else {
+ throw new UnsupportedOperationException("No alpha values are specified");
}
- long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
- createNativeChildAnimator(propertyPtr, startTime, animator);
+ }
+ long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue);
+ if (mTmpValues.dataSource != null) {
+ // Pass keyframe data to native, if any.
+ float[] dataPoints = createFloatDataPoints(mTmpValues.dataSource,
+ animator.getDuration());
+ nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length);
+ }
+ createNativeChildAnimator(propertyPtr, startTime, animator);
+ }
+
+ /**
+ * Calculate the amount of frames an animation will run based on duration.
+ */
+ private static int getFrameCount(long duration) {
+ long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
+ int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
+ int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs);
+ // We need 2 frames of data minimum.
+ numAnimFrames = Math.max(2, numAnimFrames);
+ if (numAnimFrames > MAX_SAMPLE_POINTS) {
+ Log.w("AnimatedVectorDrawable", "Duration for the animation is too long :" +
+ duration + ", the animation will subsample the keyframe or path data.");
+ numAnimFrames = MAX_SAMPLE_POINTS;
+ }
+ return numAnimFrames;
}
// These are the data points that define the value of the animating properties.
@@ -1276,11 +1309,9 @@
// a point on the path corresponds to the values of translateX and translateY.
// TODO: (Optimization) We should pass the path down in native and chop it into segments
// in native.
- private static float[] createDataPoints(
+ private static float[] createFloatDataPoints(
PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
- long frameIntervalNanos = Choreographer.getInstance().getFrameIntervalNanos();
- int animIntervalMs = (int) (frameIntervalNanos / TimeUtils.NANOS_PER_MS);
- int numAnimFrames = (int) Math.ceil(((double) duration) / animIntervalMs);
+ int numAnimFrames = getFrameCount(duration);
float values[] = new float[numAnimFrames];
float lastFrame = numAnimFrames - 1;
for (int i = 0; i < numAnimFrames; i++) {
@@ -1290,6 +1321,18 @@
return values;
}
+ private static int[] createIntDataPoints(
+ PropertyValuesHolder.PropertyValues.DataSource dataSource, long duration) {
+ int numAnimFrames = getFrameCount(duration);
+ int values[] = new int[numAnimFrames];
+ float lastFrame = numAnimFrames - 1;
+ for (int i = 0; i < numAnimFrames; i++) {
+ float fraction = i / lastFrame;
+ values[i] = (Integer) dataSource.getValueAtFraction(fraction);
+ }
+ return values;
+ }
+
private void createNativeChildAnimator(long propertyPtr, long extraDelay,
ObjectAnimator animator) {
long duration = animator.getDuration();
@@ -1566,6 +1609,7 @@
private static native long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
float endValue);
private static native void nSetPropertyHolderData(long nativePtr, float[] data, int length);
+ private static native void nSetPropertyHolderData(long nativePtr, int[] data, int length);
private static native void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
private static native void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id);
private static native void nEnd(long animatorSetPtr);
diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp
index 0932d65..6ba0ab5 100644
--- a/libs/hwui/PropertyValuesHolder.cpp
+++ b/libs/hwui/PropertyValuesHolder.cpp
@@ -25,7 +25,27 @@
using namespace VectorDrawable;
-float PropertyValuesHolder::getValueFromData(float fraction) {
+inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
+ return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
+}
+
+// TODO: Add a test for this
+void ColorEvaluator::evaluate(SkColor* outColor,
+ const SkColor& fromColor, const SkColor& toColor, float fraction) const {
+ U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
+ U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
+ U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
+ U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
+ *outColor = SkColorSetARGB(alpha, red, green, blue);
+}
+
+void PathEvaluator::evaluate(PathData* out,
+ const PathData& from, const PathData& to, float fraction) const {
+ VectorDrawableUtils::interpolatePaths(out, from, to, fraction);
+}
+
+template<typename T>
+const T PropertyValuesHolderImpl<T>::getValueFromData(float fraction) const {
if (mDataSource.size() == 0) {
LOG_ALWAYS_FATAL("No data source is defined");
return 0;
@@ -41,57 +61,44 @@
int lowIndex = floor(fraction);
fraction -= lowIndex;
- float value = mDataSource[lowIndex] * (1.0f - fraction)
- + mDataSource[lowIndex + 1] * fraction;
+ T value;
+ mEvaluator->evaluate(&value, mDataSource[lowIndex], mDataSource[lowIndex + 1], fraction);
return value;
}
-void GroupPropertyValuesHolder::setFraction(float fraction) {
- float animatedValue;
+template<typename T>
+const T PropertyValuesHolderImpl<T>::calculateAnimatedValue(float fraction) const {
if (mDataSource.size() > 0) {
- animatedValue = getValueFromData(fraction);
+ return getValueFromData(fraction);
} else {
- animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+ T value;
+ mEvaluator->evaluate(&value, mStartValue, mEndValue, fraction);
+ return value;
}
+}
+
+void GroupPropertyValuesHolder::setFraction(float fraction) {
+ float animatedValue = calculateAnimatedValue(fraction);
mGroup->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
}
-inline U8CPU lerp(U8CPU fromValue, U8CPU toValue, float fraction) {
- return (U8CPU) (fromValue * (1 - fraction) + toValue * fraction);
-}
-
-// TODO: Add a test for this
-SkColor FullPathColorPropertyValuesHolder::interpolateColors(SkColor fromColor, SkColor toColor,
- float fraction) {
- U8CPU alpha = lerp(SkColorGetA(fromColor), SkColorGetA(toColor), fraction);
- U8CPU red = lerp(SkColorGetR(fromColor), SkColorGetR(toColor), fraction);
- U8CPU green = lerp(SkColorGetG(fromColor), SkColorGetG(toColor), fraction);
- U8CPU blue = lerp(SkColorGetB(fromColor), SkColorGetB(toColor), fraction);
- return SkColorSetARGB(alpha, red, green, blue);
-}
-
void FullPathColorPropertyValuesHolder::setFraction(float fraction) {
- SkColor animatedValue = interpolateColors(mStartValue, mEndValue, fraction);
+ SkColor animatedValue = calculateAnimatedValue(fraction);
mFullPath->mutateProperties()->setColorPropertyValue(mPropertyId, animatedValue);
}
void FullPathPropertyValuesHolder::setFraction(float fraction) {
- float animatedValue;
- if (mDataSource.size() > 0) {
- animatedValue = getValueFromData(fraction);
- } else {
- animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
- }
+ float animatedValue = calculateAnimatedValue(fraction);
mFullPath->mutateProperties()->setPropertyValue(mPropertyId, animatedValue);
}
void PathDataPropertyValuesHolder::setFraction(float fraction) {
- VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction);
+ mEvaluator->evaluate(&mPathData, mStartValue, mEndValue, fraction);
mPath->mutateProperties()->setData(mPathData);
}
void RootAlphaPropertyValuesHolder::setFraction(float fraction) {
- float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction;
+ float animatedValue = calculateAnimatedValue(fraction);
mTree->mutateProperties()->setRootAlpha(animatedValue);
}
diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h
index b905fae..432f8ba 100644
--- a/libs/hwui/PropertyValuesHolder.h
+++ b/libs/hwui/PropertyValuesHolder.h
@@ -31,91 +31,130 @@
class ANDROID_API PropertyValuesHolder {
public:
virtual void setFraction(float fraction) = 0;
- void setPropertyDataSource(float* dataSource, int length) {
- mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
- }
- float getValueFromData(float fraction);
- virtual ~PropertyValuesHolder() {}
-protected:
- std::vector<float> mDataSource;
+ virtual ~PropertyValuesHolder() {}
};
-class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder {
+template <typename T>
+class Evaluator {
+public:
+ virtual void evaluate(T* out, const T& from, const T& to, float fraction) const {};
+ virtual ~Evaluator() {}
+};
+
+class FloatEvaluator : public Evaluator<float> {
+public:
+ virtual void evaluate(float* out, const float& from, const float& to, float fraction)
+ const override {
+ *out = from * (1 - fraction) + to * fraction;
+ }
+};
+
+class ANDROID_API ColorEvaluator : public Evaluator<SkColor> {
+public:
+ virtual void evaluate(SkColor* outColor, const SkColor& from, const SkColor& to,
+ float fraction) const override;
+};
+
+class ANDROID_API PathEvaluator : public Evaluator<PathData> {
+ virtual void evaluate(PathData* out, const PathData& from, const PathData& to, float fraction)
+ const override;
+};
+
+template <typename T>
+class ANDROID_API PropertyValuesHolderImpl : public PropertyValuesHolder {
+public:
+ PropertyValuesHolderImpl(const T& startValue, const T& endValue)
+ : mStartValue(startValue)
+ , mEndValue(endValue) {}
+ void setPropertyDataSource(T* dataSource, int length) {
+ mDataSource.insert(mDataSource.begin(), dataSource, dataSource + length);
+ }
+ // Calculate the animated value from the data source.
+ const T getValueFromData(float fraction) const;
+ // Convenient method to favor getting animated value from data source. If no data source is set
+ // fall back to linear interpolation.
+ const T calculateAnimatedValue(float fraction) const;
+protected:
+ std::unique_ptr<Evaluator<T>> mEvaluator = nullptr;
+ // This contains uniformly sampled data throughout the animation duration. The first element
+ // should be the start value and the last should be the end value of the animation. When the
+ // data source is set, we'll favor data source over the linear interpolation of start/end value
+ // for calculation of animated value.
+ std::vector<T> mDataSource;
+ T mStartValue;
+ T mEndValue;
+};
+
+class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue,
float endValue)
- : mGroup(ptr)
- , mPropertyId(propertyId)
- , mStartValue(startValue)
- , mEndValue(endValue){
+ : PropertyValuesHolderImpl(startValue, endValue)
+ , mGroup(ptr)
+ , mPropertyId(propertyId) {
+ mEvaluator.reset(new FloatEvaluator());
}
void setFraction(float fraction) override;
private:
VectorDrawable::Group* mGroup;
int mPropertyId;
- float mStartValue;
- float mEndValue;
};
-class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolderImpl<SkColor> {
public:
- FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue,
- int32_t endValue)
- : mFullPath(ptr)
- , mPropertyId(propertyId)
- , mStartValue(startValue)
- , mEndValue(endValue) {};
+ FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId,
+ SkColor startValue, SkColor endValue)
+ : PropertyValuesHolderImpl(startValue, endValue)
+ , mFullPath(ptr)
+ , mPropertyId(propertyId) {
+ mEvaluator.reset(new ColorEvaluator());
+ }
void setFraction(float fraction) override;
static SkColor interpolateColors(SkColor fromColor, SkColor toColor, float fraction);
private:
VectorDrawable::FullPath* mFullPath;
int mPropertyId;
- int32_t mStartValue;
- int32_t mEndValue;
};
-class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API FullPathPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue,
float endValue)
- : mFullPath(ptr)
- , mPropertyId(propertyId)
- , mStartValue(startValue)
- , mEndValue(endValue) {};
+ : PropertyValuesHolderImpl(startValue, endValue)
+ , mFullPath(ptr)
+ , mPropertyId(propertyId) {
+ mEvaluator.reset(new FloatEvaluator());
+ };
void setFraction(float fraction) override;
private:
VectorDrawable::FullPath* mFullPath;
int mPropertyId;
- float mStartValue;
- float mEndValue;
};
-class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolderImpl<PathData> {
public:
PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue,
PathData* endValue)
- : mPath(ptr)
- , mStartValue(*startValue)
- , mEndValue(*endValue) {};
+ : PropertyValuesHolderImpl(*startValue, *endValue)
+ , mPath(ptr) {
+ mEvaluator.reset(new PathEvaluator());
+ };
void setFraction(float fraction) override;
private:
VectorDrawable::Path* mPath;
PathData mPathData;
- PathData mStartValue;
- PathData mEndValue;
};
-class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder {
+class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolderImpl<float> {
public:
RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue)
- : mTree(tree)
- , mStartValue(startValue)
- , mEndValue(endValue) {}
+ : PropertyValuesHolderImpl(startValue, endValue)
+ , mTree(tree) {
+ mEvaluator.reset(new FloatEvaluator());
+ }
void setFraction(float fraction) override;
private:
VectorDrawable::Tree* mTree;
- float mStartValue;
- float mEndValue;
};
}
}