diff options
author | 2016-02-04 20:04:10 +0000 | |
---|---|---|
committer | 2016-02-04 20:59:00 +0000 | |
commit | 5a11e8d0ba21624025b89ac63bbd18befa55be0e (patch) | |
tree | 5166f73696e1ea08cde286757403fa944f40efc0 | |
parent | 95085d154b1ea6b4db3ae14d39a1c8c8a6560f78 (diff) |
Revert "VectorDrawable native rendering - Step 4 of MANY"
b/26949340 and b/26975469, b/26975079 as well
This reverts commit f276acd98457bcaabc9e79a17a736b3b484f005e.
Change-Id: I4b55177daf0d289bc03604c71fd4bf579f65073a
29 files changed, 241 insertions, 1600 deletions
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 980329fe31c8..1ab55dd7c1d9 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -1030,20 +1030,6 @@ public final class AnimatorSet extends Animator { } } - /** - * @hide - * TODO: For animatorSet defined in XML, we can use a flag to indicate what the play order - * if defined (i.e. sequential or together), then we can use the flag instead of calculate - * dynamically. - * @return whether all the animators in the set are supposed to play together - */ - public boolean shouldPlayTogether() { - updateAnimatorsDuration(); - createDependencyGraph(); - // All the child nodes are set out to play right after the delay animation - return mRootNode.mChildNodes.size() == mNodes.size() - 1; - } - @Override public long getTotalDuration() { updateAnimatorsDuration(); diff --git a/core/java/android/animation/PathKeyframes.java b/core/java/android/animation/PathKeyframes.java index 8230ac5bbfc5..2a47b68a41b0 100644 --- a/core/java/android/animation/PathKeyframes.java +++ b/core/java/android/animation/PathKeyframes.java @@ -231,7 +231,7 @@ class PathKeyframes implements Keyframes { } } - abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes { + private abstract static class IntKeyframesBase extends SimpleKeyframes implements IntKeyframes { @Override public Class getType() { return Integer.class; @@ -243,7 +243,7 @@ class PathKeyframes implements Keyframes { } } - abstract static class FloatKeyframesBase extends SimpleKeyframes + private abstract static class FloatKeyframesBase extends SimpleKeyframes implements FloatKeyframes { @Override public Class getType() { diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 6ba5b968dfe7..e993cca9e325 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -21,7 +21,6 @@ import android.graphics.PointF; import android.util.FloatProperty; import android.util.IntProperty; import android.util.Log; -import android.util.PathParser; import android.util.Property; import java.lang.reflect.InvocationTargetException; @@ -1047,43 +1046,6 @@ public class PropertyValuesHolder implements Cloneable { return mAnimatedValue; } - /** - * PropertyValuesHolder is Animators use to hold internal animation related data. - * Therefore, in order to replicate the animation behavior, we need to get data out of - * PropertyValuesHolder. - * @hide - */ - public void getPropertyValues(PropertyValues values) { - init(); - values.propertyName = mPropertyName; - values.type = mValueType; - values.startValue = mKeyframes.getValue(0); - if (values.startValue instanceof PathParser.PathData) { - // PathData evaluator returns the same mutable PathData object when query fraction, - // so we have to make a copy here. - values.startValue = new PathParser.PathData((PathParser.PathData) values.startValue); - } - values.endValue = mKeyframes.getValue(1); - if (values.endValue instanceof PathParser.PathData) { - // PathData evaluator returns the same mutable PathData object when query fraction, - // so we have to make a copy here. - values.endValue = new PathParser.PathData((PathParser.PathData) values.endValue); - } - // 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) - values.dataSource = new PropertyValues.DataSource() { - @Override - public Object getValueAtFraction(float fraction) { - return mKeyframes.getValue(fraction); - } - }; - } else { - values.dataSource = null; - } - } - @Override public String toString() { return mPropertyName + ": " + mKeyframes.toString(); @@ -1639,24 +1601,6 @@ public class PropertyValuesHolder implements Cloneable { } }; - /** - * @hide - */ - public static class PropertyValues { - public String propertyName; - public Class type; - public Object startValue; - public Object endValue; - public DataSource dataSource = null; - public interface DataSource { - Object getValueAtFraction(float fraction); - } - public String toString() { - return ("property name: " + propertyName + ", type: " + type + ", startValue: " - + startValue.toString() + ", endValue: " + endValue.toString()); - } - } - native static private long nGetIntMethod(Class targetClass, String methodName); native static private long nGetFloatMethod(Class targetClass, String methodName); native static private long nGetMultipleIntMethod(Class targetClass, String methodName, diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java index 29a72fdf2288..78d5bcd90624 100644 --- a/core/java/android/util/PathParser.java +++ b/core/java/android/util/PathParser.java @@ -104,7 +104,6 @@ public class PathParser { } super.finalize(); } - } /** diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 7017ff5a3fa0..3122c0be30fe 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -22,7 +22,6 @@ import android.graphics.Matrix; import android.graphics.Outline; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.drawable.AnimatedVectorDrawable; /** * <p>A display list records a series of graphics related operations and can replay @@ -775,14 +774,6 @@ public class RenderNode { mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); } - public void addAnimator(AnimatedVectorDrawable.VectorDrawableAnimator animatorSet) { - if (mOwningView == null || mOwningView.mAttachInfo == null) { - throw new IllegalStateException("Cannot start this animator on a detached view!"); - } - nAddAnimator(mNativeRenderNode, animatorSet.getAnimatorNativePtr()); - mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); - } - public void endAllAnimators() { nEndAllAnimators(mNativeRenderNode); } diff --git a/core/java/android/view/RenderNodeAnimatorSetHelper.java b/core/java/android/view/RenderNodeAnimatorSetHelper.java deleted file mode 100644 index ba592d29fa3d..000000000000 --- a/core/java/android/view/RenderNodeAnimatorSetHelper.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 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 android.view; - -import android.animation.TimeInterpolator; -import com.android.internal.view.animation.FallbackLUTInterpolator; -import com.android.internal.view.animation.NativeInterpolatorFactory; -import com.android.internal.view.animation.NativeInterpolatorFactoryHelper; - -/** - * This is a helper class to get access to methods and fields needed for RenderNodeAnimatorSet - * that are internal or package private to android.view package. - * - * @hide - */ -public class RenderNodeAnimatorSetHelper { - - public static RenderNode getTarget(DisplayListCanvas recordingCanvas) { - return recordingCanvas.mNode; - } - - public static long createNativeInterpolator(TimeInterpolator interpolator, long - duration) { - if (interpolator == null) { - // create LinearInterpolator - return NativeInterpolatorFactoryHelper.createLinearInterpolator(); - } else if (RenderNodeAnimator.isNativeInterpolator(interpolator)) { - return ((NativeInterpolatorFactory)interpolator).createNativeInterpolator(); - } else { - return FallbackLUTInterpolator.createNativeInterpolator(interpolator, duration); - } - } - -} diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 1b6b53ae49f4..ffa3fa631b82 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -51,7 +51,6 @@ LOCAL_SRC_FILES:= \ android_database_SQLiteConnection.cpp \ android_database_SQLiteGlobal.cpp \ android_database_SQLiteDebug.cpp \ - android_graphics_drawable_AnimatedVectorDrawable.cpp \ android_graphics_drawable_VectorDrawable.cpp \ android_view_DisplayEventReceiver.cpp \ android_view_DisplayListCanvas.cpp \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 223fc1af46d5..2e45f8c4d9c0 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -131,7 +131,6 @@ extern int register_android_graphics_Rasterizer(JNIEnv* env); extern int register_android_graphics_Region(JNIEnv* env); extern int register_android_graphics_SurfaceTexture(JNIEnv* env); extern int register_android_graphics_Xfermode(JNIEnv* env); -extern int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env); extern int register_android_graphics_drawable_VectorDrawable(JNIEnv* env); extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env); extern int register_android_graphics_pdf_PdfEditor(JNIEnv* env); @@ -1322,7 +1321,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_graphics_Typeface), REG_JNI(register_android_graphics_Xfermode), REG_JNI(register_android_graphics_YuvImage), - REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable), REG_JNI(register_android_graphics_drawable_VectorDrawable), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_graphics_pdf_PdfEditor), diff --git a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp b/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp deleted file mode 100644 index 7a3c598e0aed..000000000000 --- a/core/jni/android_graphics_drawable_AnimatedVectorDrawable.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ -#define LOG_TAG "OpenGLRenderer" - -#include "jni.h" -#include "GraphicsJNI.h" -#include "core_jni_helpers.h" -#include "log/log.h" - -#include "Animator.h" -#include "Interpolator.h" -#include "PropertyValuesAnimatorSet.h" -#include "PropertyValuesHolder.h" -#include "VectorDrawable.h" - -namespace android { -using namespace uirenderer; -using namespace VectorDrawable; - -static struct { - jclass clazz; - jmethodID callOnFinished; -} gVectorDrawableAnimatorClassInfo; - -static JNIEnv* getEnv(JavaVM* vm) { - JNIEnv* env; - if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { - return 0; - } - return env; -} - -static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener) { - class AnimationListenerBridge : public AnimationListener { - public: - AnimationListenerBridge(JNIEnv* env, jobject finishListener) { - mFinishListener = env->NewGlobalRef(finishListener); - env->GetJavaVM(&mJvm); - } - - virtual ~AnimationListenerBridge() { - if (mFinishListener) { - onAnimationFinished(NULL); - } - } - - virtual void onAnimationFinished(BaseRenderNodeAnimator*) { - LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); - JNIEnv* env = getEnv(mJvm); - env->CallStaticVoidMethod( - gVectorDrawableAnimatorClassInfo.clazz, - gVectorDrawableAnimatorClassInfo.callOnFinished, - mFinishListener); - releaseJavaObject(); - } - - private: - void releaseJavaObject() { - JNIEnv* env = getEnv(mJvm); - env->DeleteGlobalRef(mFinishListener); - mFinishListener = NULL; - } - - JavaVM* mJvm; - jobject mFinishListener; - }; - return new AnimationListenerBridge(env, finishListener); -} - -static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, - jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) { - PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); - Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); - set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount); -} - -static jlong createAnimatorSet(JNIEnv*, jobject) { - PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet(); - return reinterpret_cast<jlong>(animatorSet); -} - -static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, - jfloat startValue, jfloat endValue) { - VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(nativePtr); - GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId, - startValue, endValue); - return reinterpret_cast<jlong>(newHolder); -} - -static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr, - jlong endValuePtr) { - VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(nativePtr); - PathData* startData = reinterpret_cast<PathData*>(startValuePtr); - PathData* endData = reinterpret_cast<PathData*>(endValuePtr); - PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path, - startData, endData); - return reinterpret_cast<jlong>(newHolder); -} - -static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, - int startValue, jint endValue) { - VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); - FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath, - propertyId, startValue, endValue); - return reinterpret_cast<jlong>(newHolder); -} - -static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, - float startValue, jfloat endValue) { - VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); - FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath, - propertyId, startValue, endValue); - return reinterpret_cast<jlong>(newHolder); -} - -static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue, - float endValue) { - VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(nativePtr); - RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree, - startValue, endValue); - return reinterpret_cast<jlong>(newHolder); -} -static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, - jfloatArray srcData, jint length) { - - jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr); - PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); - holder->setPropertyDataSource(propertyData, length); - env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); -} -static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { - PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - // TODO: keep a ref count in finish listener - AnimationListener* listener = createAnimationListener(env, finishListener); - set->start(listener); -} - -static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener) { - // TODO: implement reverse -} - -static void end(JNIEnv*, jobject, jlong animatorSetPtr) { - PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - set->end(); -} - -static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { - PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); - set->reset(); -} - -static const JNINativeMethod gMethods[] = { - {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, - {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator}, - {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder}, - {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder}, - {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder}, - {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, - {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, - {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData}, - {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)start}, - {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V", (void*)reverse}, - {"nEnd", "!(J)V", (void*)end}, - {"nReset", "!(J)V", (void*)reset}, -}; - -const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator"; -int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { - gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); - gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, - gVectorDrawableAnimatorClassInfo.clazz); - - gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( - env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", - "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimator;)V"); - return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", - gMethods, NELEM(gMethods)); -} - -}; // namespace android diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp index e88287644555..563ec8bd9834 100644 --- a/core/jni/android_graphics_drawable_VectorDrawable.cpp +++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp @@ -32,6 +32,11 @@ static jlong createTree(JNIEnv*, jobject, jlong groupPtr) { return reinterpret_cast<jlong>(tree); } +static void deleteTree(JNIEnv*, jobject, jlong treePtr) { + VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr); + delete tree; +} + static void setTreeViewportSize(JNIEnv*, jobject, jlong treePtr, jfloat viewportWidth, jfloat viewportHeight) { VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(treePtr); @@ -328,6 +333,7 @@ static void setTrimPathOffset(JNIEnv*, jobject, jlong fullPathPtr, jfloat trimPa static const JNINativeMethod gMethods[] = { {"nCreateRenderer", "!(J)J", (void*)createTree}, + {"nDestroyRenderer", "!(J)V", (void*)deleteTree}, {"nSetRendererViewportSize", "!(JFF)V", (void*)setTreeViewportSize}, {"nSetRootAlpha", "!(JF)Z", (void*)setRootAlpha}, {"nGetRootAlpha", "!(J)F", (void*)getRootAlpha}, diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index 0a3e27e94c06..c48c371ebdfd 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -19,10 +19,6 @@ import android.animation.AnimatorInflater; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.Animator.AnimatorListener; -import android.animation.PropertyValuesHolder; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.animation.ObjectAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.ColorStateList; @@ -38,23 +34,14 @@ import android.graphics.Rect; import android.util.ArrayMap; import android.util.AttributeSet; import android.util.Log; -import android.util.LongArray; -import android.util.PathParser; -import android.util.TimeUtils; -import android.view.Choreographer; -import android.view.DisplayListCanvas; -import android.view.RenderNode; -import android.view.RenderNodeAnimatorSetHelper; import android.view.View; import com.android.internal.R; -import com.android.internal.util.VirtualRefBasePtr; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; -import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -151,7 +138,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { private static final boolean DBG_ANIMATION_VECTOR_DRAWABLE = false; /** Local, mutable animator set. */ - private final VectorDrawableAnimator mAnimatorSet = new VectorDrawableAnimator(); + private final AnimatorSet mAnimatorSet = new AnimatorSet(); /** * The resources against which this drawable was created. Used to attempt @@ -213,9 +200,6 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { @Override public void draw(Canvas canvas) { - if (canvas.isHardwareAccelerated()) { - mAnimatorSet.recordLastSeenTarget((DisplayListCanvas) canvas); - } mAnimatedVectorState.mVectorDrawable.draw(canvas); if (isStarted()) { invalidateSelf(); @@ -598,8 +582,9 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { * Resets the AnimatedVectorDrawable to the start state as specified in the animators. */ public void reset() { - mAnimatorSet.reset(); - invalidateSelf(); + // TODO: Use reverse or seek to implement reset, when AnimatorSet supports them. + start(); + mAnimatorSet.cancel(); } @Override @@ -618,12 +603,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { @NonNull private void ensureAnimatorSet() { if (!mHasAnimatorSet) { - // TODO: Skip the AnimatorSet creation and init the VectorDrawableAnimator directly - // with a list of LocalAnimators. - AnimatorSet set = new AnimatorSet(); - mAnimatedVectorState.prepareLocalAnimators(set, mRes); + mAnimatedVectorState.prepareLocalAnimators(mAnimatorSet, mRes); mHasAnimatorSet = true; - mAnimatorSet.initWithAnimatorSet(set); mRes = null; } } @@ -713,13 +694,13 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { } }; } - mAnimatorSet.setListener(mAnimatorListener); + mAnimatorSet.addListener(mAnimatorListener); } // A helper function to clean up the animator listener in the mAnimatorSet. private void removeAnimatorSetListener() { if (mAnimatorListener != null) { - mAnimatorSet.removeListener(); + mAnimatorSet.removeListener(mAnimatorListener); mAnimatorListener = null; } } @@ -748,407 +729,4 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 { mAnimationCallbacks.clear(); } - - /** - * @hide - */ - public static class VectorDrawableAnimator { - private AnimatorListener mListener = null; - private final LongArray mStartDelays = new LongArray(); - private PropertyValuesHolder.PropertyValues mTmpValues = - new PropertyValuesHolder.PropertyValues(); - private long mSetPtr = 0; - private boolean mContainsSequentialAnimators = false; - private boolean mStarted = false; - private boolean mInitialized = false; - private boolean mAnimationPending = false; - private boolean mIsReversible = false; - // TODO: Consider using NativeAllocationRegistery to track native allocation - private final VirtualRefBasePtr mSetRefBasePtr; - private WeakReference<RenderNode> mTarget = null; - private WeakReference<RenderNode> mLastSeenTarget = null; - - - VectorDrawableAnimator() { - mSetPtr = nCreateAnimatorSet(); - // Increment ref count on native AnimatorSet, so it doesn't get released before Java - // side is done using it. - mSetRefBasePtr = new VirtualRefBasePtr(mSetPtr); - } - - private void initWithAnimatorSet(AnimatorSet set) { - if (mInitialized) { - // Already initialized - throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " + - "re-initialized"); - } - parseAnimatorSet(set, 0); - mInitialized = true; - - // Check reversible. - if (mContainsSequentialAnimators) { - mIsReversible = false; - } else { - // Check if there's any start delay set on child - for (int i = 0; i < mStartDelays.size(); i++) { - if (mStartDelays.get(i) > 0) { - mIsReversible = false; - return; - } - } - } - mIsReversible = true; - } - - private void parseAnimatorSet(AnimatorSet set, long startTime) { - ArrayList<Animator> animators = set.getChildAnimations(); - - boolean playTogether = set.shouldPlayTogether(); - // Convert AnimatorSet to VectorDrawableAnimator - for (int i = 0; i < animators.size(); i++) { - Animator animator = animators.get(i); - // Here we only support ObjectAnimator - if (animator instanceof AnimatorSet) { - parseAnimatorSet((AnimatorSet) animator, startTime); - } else if (animator instanceof ObjectAnimator) { - createRTAnimator((ObjectAnimator) animator, startTime); - } // ignore ValueAnimators and others because they don't directly modify VD - // therefore will be useless to AVD. - - if (!playTogether) { - // Assume not play together means play sequentially - startTime += animator.getTotalDuration(); - mContainsSequentialAnimators = true; - } - } - } - - // TODO: This method reads animation data from already parsed Animators. We need to move - // this step further up the chain in the parser to avoid the detour. - private void createRTAnimator(ObjectAnimator animator, long startTime) { - PropertyValuesHolder[] values = animator.getValues(); - Object target = animator.getTarget(); - if (target instanceof VectorDrawable.VGroup) { - createRTAnimatorForGroup(values, animator, (VectorDrawable.VGroup) target, - startTime); - } else if (target instanceof VectorDrawable.VPath) { - for (int i = 0; i < values.length; i++) { - values[i].getPropertyValues(mTmpValues); - if (mTmpValues.endValue instanceof PathParser.PathData && - mTmpValues.propertyName.equals("pathData")) { - createRTAnimatorForPath(animator, (VectorDrawable.VPath) target, - startTime); - } else if (target instanceof VectorDrawable.VFullPath) { - createRTAnimatorForFullPath(animator, (VectorDrawable.VFullPath) target, - startTime); - } else { - throw new IllegalArgumentException("ClipPath only supports PathData " + - "property"); - } - - } - } else if (target instanceof VectorDrawable.VectorDrawableState) { - createRTAnimatorForRootGroup(values, animator, - (VectorDrawable.VectorDrawableState) target, startTime); - } else { - // Should never get here - throw new UnsupportedOperationException("Target should be either VGroup, VPath, " + - "or ConstantState, " + target.getClass() + " is not supported"); - } - } - - private void createRTAnimatorForGroup(PropertyValuesHolder[] values, - ObjectAnimator animator, VectorDrawable.VGroup target, - long startTime) { - - long nativePtr = target.getNativePtr(); - int propertyId; - for (int i = 0; i < values.length; i++) { - // TODO: We need to support the rare case in AVD where no start value is provided - values[i].getPropertyValues(mTmpValues); - propertyId = VectorDrawable.VGroup.getPropertyIndex(mTmpValues.propertyName); - if (mTmpValues.type != Float.class && mTmpValues.type != float.class) { - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.e(LOGTAG, "Unsupported type: " + - mTmpValues.type + ". Only float value is supported for Groups."); - } - continue; - } - if (propertyId < 0) { - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.e(LOGTAG, "Unsupported property: " + - mTmpValues.propertyName + " for Vector Drawable Group"); - } - continue; - } - long propertyPtr = nCreateGroupPropertyHolder(nativePtr, propertyId, - (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); - if (mTmpValues.dataSource != null) { - float[] dataPoints = createDataPoints(mTmpValues.dataSource, animator - .getDuration()); - nSetPropertyHolderData(propertyPtr, dataPoints, dataPoints.length); - } - createNativeChildAnimator(propertyPtr, startTime, animator); - } - } - private void createRTAnimatorForPath( ObjectAnimator animator, VectorDrawable.VPath target, - long startTime) { - - long nativePtr = target.getNativePtr(); - long startPathDataPtr = ((PathParser.PathData) mTmpValues.startValue) - .getNativePtr(); - long endPathDataPtr = ((PathParser.PathData) mTmpValues.endValue) - .getNativePtr(); - long propertyPtr = nCreatePathDataPropertyHolder(nativePtr, startPathDataPtr, - endPathDataPtr); - createNativeChildAnimator(propertyPtr, startTime, animator); - } - - private void createRTAnimatorForFullPath(ObjectAnimator animator, - VectorDrawable.VFullPath target, long startTime) { - - int propertyId = target.getPropertyIndex(mTmpValues.propertyName); - long propertyPtr; - long nativePtr = target.getNativePtr(); - if (mTmpValues.type == Float.class || mTmpValues.type == float.class) { - if (propertyId < 0) { - throw new IllegalArgumentException("Property: " + mTmpValues - .propertyName + " is not supported for FullPath"); - } - propertyPtr = nCreatePathPropertyHolder(nativePtr, propertyId, - (Float) mTmpValues.startValue, (Float) mTmpValues.endValue); - - } else if (mTmpValues.type == Integer.class || mTmpValues.type == int.class) { - propertyPtr = nCreatePathColorPropertyHolder(nativePtr, propertyId, - (Integer) mTmpValues.startValue, (Integer) mTmpValues.endValue); - } else { - throw new UnsupportedOperationException("Unsupported type: " + - mTmpValues.type + ". Only float, int or PathData value is " + - "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")) { - 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; - } - } - if (startValue == null && endValue == null) { - throw new UnsupportedOperationException("No alpha values are specified"); - } - long propertyPtr = nCreateRootAlphaPropertyHolder(nativePtr, startValue, endValue); - createNativeChildAnimator(propertyPtr, startTime, animator); - } - - // These are the data points that define the value of the animating properties. - // e.g. translateX and translateY can animate along a Path, at any fraction in [0, 1] - // 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( - 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); - float values[] = new float[numAnimFrames]; - float lastFrame = numAnimFrames - 1; - for (int i = 0; i < numAnimFrames; i++) { - float fraction = i / lastFrame; - values[i] = (Float) dataSource.getValueAtFraction(fraction); - } - return values; - } - - private void createNativeChildAnimator(long propertyPtr, long extraDelay, - ObjectAnimator animator) { - long duration = animator.getDuration(); - int repeatCount = animator.getRepeatCount(); - long startDelay = extraDelay + animator.getStartDelay(); - TimeInterpolator interpolator = animator.getInterpolator(); - long nativeInterpolator = - RenderNodeAnimatorSetHelper.createNativeInterpolator(interpolator, duration); - - startDelay *= ValueAnimator.getDurationScale(); - duration *= ValueAnimator.getDurationScale(); - - mStartDelays.add(startDelay); - nAddAnimator(mSetPtr, propertyPtr, nativeInterpolator, startDelay, duration, - repeatCount); - } - - /** - * Holds a weak reference to the target that was last seen (through the DisplayListCanvas - * in the last draw call), so that when animator set needs to start, we can add the animator - * to the last seen RenderNode target and start right away. - */ - protected void recordLastSeenTarget(DisplayListCanvas canvas) { - if (mAnimationPending) { - mLastSeenTarget = new WeakReference<RenderNode>( - RenderNodeAnimatorSetHelper.getTarget(canvas)); - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "Target is set in the next frame"); - } - mAnimationPending = false; - start(); - } else { - mLastSeenTarget = new WeakReference<RenderNode>( - RenderNodeAnimatorSetHelper.getTarget(canvas)); - } - - } - - private boolean setTarget(RenderNode node) { - if (mTarget != null && mTarget.get() != null) { - // TODO: Maybe we want to support target change. - throw new IllegalStateException("Target already set!"); - } - - node.addAnimator(this); - mTarget = new WeakReference<RenderNode>(node); - return true; - } - - private boolean useLastSeenTarget() { - if (mLastSeenTarget != null && mLastSeenTarget.get() != null) { - setTarget(mLastSeenTarget.get()); - return true; - } - return false; - } - - public void start() { - if (!mInitialized) { - return; - } - - if (mStarted) { - return; - } - - if (!useLastSeenTarget()) { - mAnimationPending = true; - return; - } - - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "Target is set. Starting VDAnimatorSet from java"); - } - - nStart(mSetPtr, this); - if (mListener != null) { - mListener.onAnimationStart(null); - } - mStarted = true; - } - - public void end() { - if (mInitialized && mStarted) { - nEnd(mSetPtr); - onAnimationEnd(); - } - } - - void reset() { - if (!mInitialized) { - return; - } - // TODO: Need to implement reset. - Log.w(LOGTAG, "Reset is yet to be implemented"); - nReset(mSetPtr); - } - - // Current (imperfect) Java AnimatorSet cannot be reversed when the set contains sequential - // animators or when the animator set has a start delay - void reverse() { - if (!mIsReversible) { - return; - } - // TODO: Need to support reverse (non-public API) - Log.w(LOGTAG, "Reverse is yet to be implemented"); - nReverse(mSetPtr, this); - } - - public long getAnimatorNativePtr() { - return mSetPtr; - } - - boolean canReverse() { - return mIsReversible; - } - - boolean isStarted() { - return mStarted; - } - - boolean isRunning() { - if (!mInitialized) { - return false; - } - return mStarted; - } - - void setListener(AnimatorListener listener) { - mListener = listener; - } - - void removeListener() { - mListener = null; - } - - private void onAnimationEnd() { - mStarted = false; - if (mListener != null) { - mListener.onAnimationEnd(null); - } - mTarget = null; - } - - // onFinished: should be called from native - private static void callOnFinished(VectorDrawableAnimator set) { - if (DBG_ANIMATION_VECTOR_DRAWABLE) { - Log.d(LOGTAG, "on finished called from native"); - } - set.onAnimationEnd(); - } - } - - private static native long nCreateAnimatorSet(); - private static native void nAddAnimator(long setPtr, long propertyValuesHolder, - long nativeInterpolator, long startDelay, long duration, int repeatCount); - - private static native long nCreateGroupPropertyHolder(long nativePtr, int propertyId, - float startValue, float endValue); - - private static native long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr, - long endValuePtr); - private static native long nCreatePathColorPropertyHolder(long nativePtr, int propertyId, - int startValue, int endValue); - private static native long nCreatePathPropertyHolder(long nativePtr, int propertyId, - float startValue, float endValue); - 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 nStart(long animatorSetPtr, VectorDrawableAnimator set); - private static native void nReverse(long animatorSetPtr, VectorDrawableAnimator set); - private static native void nEnd(long animatorSetPtr); - private static native void nReset(long animatorSetPtr); } diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index f4bbc8c43d08..1fc1b83f7a6c 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -39,7 +39,6 @@ import android.util.PathParser; import android.util.Xml; import com.android.internal.R; -import com.android.internal.util.VirtualRefBasePtr; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -48,7 +47,6 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; -import java.util.HashMap; import java.util.Stack; /** @@ -524,13 +522,13 @@ public class VectorDrawable extends Drawable { public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) throws XmlPullParserException, IOException { - if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererRefBase != null) { + if (mVectorState.mRootGroup != null || mVectorState.mNativeRendererPtr != 0) { // This VD has been used to display other VD resource content, clean up. mVectorState.mRootGroup = new VGroup(); - if (mVectorState.mNativeRendererRefBase != null) { - mVectorState.mNativeRendererRefBase.release(); + if (mVectorState.mNativeRendererPtr != 0) { + nDestroyRenderer(mVectorState.mNativeRendererPtr); } - mVectorState.createNativeRenderer(mVectorState.mRootGroup.mNativePtr); + mVectorState.mNativeRendererPtr = nCreateRenderer(mVectorState.mRootGroup.mNativePtr); } final VectorDrawableState state = mVectorState; state.setDensity(Drawable.resolveDensity(r, 0)); @@ -709,7 +707,7 @@ public class VectorDrawable extends Drawable { return mVectorState.mAutoMirrored; } - static class VectorDrawableState extends ConstantState { + private static class VectorDrawableState extends ConstantState { // Variables below need to be copied (deep copy if applicable) for mutation. int[] mThemeAttrs; int mChangingConfigurations; @@ -724,7 +722,7 @@ public class VectorDrawable extends Drawable { Insets mOpticalInsets = Insets.NONE; String mRootName = null; VGroup mRootGroup; - VirtualRefBasePtr mNativeRendererRefBase = null; + long mNativeRendererPtr; int mDensity = DisplayMetrics.DENSITY_DEFAULT; final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<>(); @@ -745,7 +743,7 @@ public class VectorDrawable extends Drawable { mTintMode = copy.mTintMode; mAutoMirrored = copy.mAutoMirrored; mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); - createNativeRenderer(mRootGroup.mNativePtr); + mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr); mBaseWidth = copy.mBaseWidth; mBaseHeight = copy.mBaseHeight; @@ -760,15 +758,18 @@ public class VectorDrawable extends Drawable { } } - private void createNativeRenderer(long rootGroupPtr) { - mNativeRendererRefBase = new VirtualRefBasePtr(nCreateRenderer(rootGroupPtr)); + @Override + public void finalize() throws Throwable { + if (mNativeRendererPtr != 0) { + nDestroyRenderer(mNativeRendererPtr); + mNativeRendererPtr = 0; + } + super.finalize(); } + long getNativeRenderer() { - if (mNativeRendererRefBase == null) { - return 0; - } - return mNativeRendererRefBase.get(); + return mNativeRendererPtr; } public boolean canReuseCache() { @@ -807,7 +808,7 @@ public class VectorDrawable extends Drawable { public VectorDrawableState() { mRootGroup = new VGroup(); - createNativeRenderer(mRootGroup.mNativePtr); + mNativeRendererPtr = nCreateRenderer(mRootGroup.mNativePtr); } @Override @@ -871,16 +872,16 @@ public class VectorDrawable extends Drawable { * has changed. */ public boolean setAlpha(float alpha) { - return nSetRootAlpha(mNativeRendererRefBase.get(), alpha); + return nSetRootAlpha(mNativeRendererPtr, alpha); } @SuppressWarnings("unused") public float getAlpha() { - return nGetRootAlpha(mNativeRendererRefBase.get()); + return nGetRootAlpha(mNativeRendererPtr); } } - static class VGroup implements VObject { + private static class VGroup implements VObject { private static final int ROTATE_INDEX = 0; private static final int PIVOT_X_INDEX = 1; private static final int PIVOT_Y_INDEX = 2; @@ -890,28 +891,6 @@ public class VectorDrawable extends Drawable { private static final int TRANSLATE_Y_INDEX = 6; private static final int TRANSFORM_PROPERTY_COUNT = 7; - private static final HashMap<String, Integer> sPropertyMap = - new HashMap<String, Integer>() { - { - put("translateX", TRANSLATE_X_INDEX); - put("translateY", TRANSLATE_Y_INDEX); - put("scaleX", SCALE_X_INDEX); - put("scaleY", SCALE_Y_INDEX); - put("pivotX", PIVOT_X_INDEX); - put("pivotY", PIVOT_Y_INDEX); - put("rotation", ROTATE_INDEX); - } - }; - - static int getPropertyIndex(String propertyName) { - if (sPropertyMap.containsKey(propertyName)) { - return sPropertyMap.get(propertyName); - } else { - // property not found - return -1; - } - } - // Temp array to store transform values obtained from native. private float[] mTransform; ///////////////////////////////////////////////////// @@ -1170,7 +1149,7 @@ public class VectorDrawable extends Drawable { /** * Common Path information for clip path and normal path. */ - static abstract class VPath implements VObject { + private static abstract class VPath implements VObject { protected PathParser.PathData mPathData = null; String mPathName; @@ -1281,7 +1260,7 @@ public class VectorDrawable extends Drawable { /** * Normal path, which contains all the fill / paint information. */ - static class VFullPath extends VPath { + private static class VFullPath extends VPath { private static final int STROKE_WIDTH_INDEX = 0; private static final int STROKE_COLOR_INDEX = 1; private static final int STROKE_ALPHA_INDEX = 2; @@ -1295,20 +1274,6 @@ public class VectorDrawable extends Drawable { private static final int STROKE_MITER_LIMIT_INDEX = 10; private static final int TOTAL_PROPERTY_COUNT = 11; - private final static HashMap<String, Integer> sPropertyMap - = new HashMap<String, Integer> () { - { - put("strokeWidth", STROKE_WIDTH_INDEX); - put("strokeColor", STROKE_COLOR_INDEX); - put("strokeAlpha", STROKE_ALPHA_INDEX); - put("fillColor", FILL_COLOR_INDEX); - put("fillAlpha", FILL_ALPHA_INDEX); - put("trimPathStart", TRIM_PATH_START_INDEX); - put("trimPathEnd", TRIM_PATH_END_INDEX); - put("trimPathOffset", TRIM_PATH_OFFSET_INDEX); - } - }; - // Temp array to store property data obtained from native getter. private byte[] mPropertyData; ///////////////////////////////////////////////////// @@ -1332,14 +1297,6 @@ public class VectorDrawable extends Drawable { mFillColors = copy.mFillColors; } - int getPropertyIndex(String propertyName) { - if (!sPropertyMap.containsKey(propertyName)) { - return -1; - } else { - return sPropertyMap.get(propertyName); - } - } - @Override public boolean onStateChange(int[] stateSet) { boolean changed = false; @@ -1638,6 +1595,7 @@ public class VectorDrawable extends Drawable { } private static native long nCreateRenderer(long rootGroupPtr); + private static native void nDestroyRenderer(long rendererPtr); private static native void nSetRendererViewportSize(long rendererPtr, float viewportWidth, float viewportHeight); private static native boolean nSetRootAlpha(long rendererPtr, float alpha); diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index c232bd1101a3..1fb9ac515f03 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -78,8 +78,6 @@ hwui_src_files := \ Program.cpp \ ProgramCache.cpp \ Properties.cpp \ - PropertyValuesHolder.cpp \ - PropertyValuesAnimatorSet.cpp \ RenderBufferCache.cpp \ RenderNode.cpp \ RenderProperties.cpp \ diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 7bd2b24bf56b..5ca2a2fa37ab 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -90,9 +90,6 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) { doSetStartValue(getValue(mTarget)); } if (mStagingPlayState > mPlayState) { - if (mStagingPlayState == PlayState::Restarted) { - mStagingPlayState = PlayState::Running; - } mPlayState = mStagingPlayState; // Oh boy, we're starting! Man the battle stations! if (mPlayState == PlayState::Running) { @@ -134,11 +131,6 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { return true; } - // This should be set before setValue() so animators can query this time when setValue - // is called. - nsecs_t currentFrameTime = context.frameTimeMs(); - onPlayTimeChanged(currentFrameTime - mStartTime); - // If BaseRenderNodeAnimator is handling the delay (not typical), then // because the staging properties reflect the final value, we always need // to call setValue even if the animation isn't yet running or is still @@ -149,9 +141,8 @@ bool BaseRenderNodeAnimator::animate(AnimationContext& context) { } float fraction = 1.0f; - if (mPlayState == PlayState::Running && mDuration > 0) { - fraction = (float)(currentFrameTime - mStartTime) / mDuration; + fraction = (float)(context.frameTimeMs() - mStartTime) / mDuration; } if (fraction >= 1.0f) { fraction = 1.0f; diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 2c9c9c3fe0f9..aea95bfc1c0e 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -59,13 +59,7 @@ public: mMayRunAsync = mayRunAsync; } bool mayRunAsync() { return mMayRunAsync; } - ANDROID_API void start() { - if (mStagingPlayState == PlayState::NotStarted) { - mStagingPlayState = PlayState::Running; - } else { - mStagingPlayState = PlayState::Restarted; - } - onStagingPlayStateChanged(); } + ANDROID_API void start() { mStagingPlayState = PlayState::Running; onStagingPlayStateChanged(); } ANDROID_API void end() { mStagingPlayState = PlayState::Finished; onStagingPlayStateChanged(); } void attach(RenderNode* target); @@ -83,27 +77,10 @@ public: void forceEndNow(AnimationContext& context); protected: - // PlayState is used by mStagingPlayState and mPlayState to track the state initiated from UI - // thread and Render Thread animation state, respectively. - // From the UI thread, mStagingPlayState transition looks like - // NotStarted -> Running -> Finished - // ^ | - // | | - // Restarted <------ - // Note: For mStagingState, the Finished state (optional) is only set when the animation is - // terminated by user. - // - // On Render Thread, mPlayState transition: - // NotStart -> Running -> Finished - // ^ | - // | | - // ------------- - enum class PlayState { NotStarted, Running, Finished, - Restarted, }; BaseRenderNodeAnimator(float finalValue); @@ -116,7 +93,6 @@ protected: void callOnFinishedListener(AnimationContext& context); virtual void onStagingPlayStateChanged() {} - virtual void onPlayTimeChanged(nsecs_t playTime) {} RenderNode* mTarget; diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h index 27facdf652cd..dbd502d19fd2 100644 --- a/libs/hwui/Canvas.h +++ b/libs/hwui/Canvas.h @@ -52,13 +52,6 @@ typedef uint32_t Flags; } // namespace SaveFlags -namespace uirenderer { -namespace VectorDrawable { -class Tree; -}; -}; -typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; - class ANDROID_API Canvas { public: virtual ~Canvas() {}; @@ -224,11 +217,6 @@ public: */ virtual bool drawTextAbsolutePos() const = 0; - /** - * Draws a VectorDrawable onto the canvas. - */ - virtual void drawVectorDrawable(VectorDrawableRoot* tree); - protected: void drawTextDecorations(float x, float y, float length, const SkPaint& paint); }; diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index 3db14b55cff6..7eaa78581391 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -16,12 +16,11 @@ #include "DisplayListCanvas.h" +#include "ResourceCache.h" #include "DeferredDisplayList.h" #include "DeferredLayerUpdater.h" #include "DisplayListOp.h" -#include "ResourceCache.h" #include "RenderNode.h" -#include "VectorDrawable.h" #include "utils/PaintUtils.h" #include <SkCamera.h> @@ -413,16 +412,6 @@ void DisplayListCanvas::drawPoints(const float* points, int count, const SkPaint addDrawOp(new (alloc()) DrawPointsOp(points, count, refPaint(&paint))); } -void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { - mDisplayList->ref(tree); - const SkBitmap& bitmap = tree->getBitmapUpdateIfDirty(); - SkPaint* paint = tree->getPaint(); - const SkRect bounds = tree->getBounds(); - addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap), - 0, 0, bitmap.width(), bitmap.height(), - bounds.left(), bounds.top(), bounds.right(), bounds.bottom(), refPaint(paint))); -} - void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) { if (!glyphs || count <= 0) return; diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h index 06e72a06eaca..ad939602ec7d 100644 --- a/libs/hwui/DisplayListCanvas.h +++ b/libs/hwui/DisplayListCanvas.h @@ -206,8 +206,6 @@ public: float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) override; - virtual void drawVectorDrawable(VectorDrawableRoot* tree) override; - // Text virtual void drawText(const uint16_t* glyphs, const float* positions, int count, const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop, @@ -216,6 +214,7 @@ public: float hOffset, float vOffset, const SkPaint& paint) override; virtual bool drawTextAbsolutePos() const override { return false; } + private: CanvasState mState; diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index 185accec1ef6..c8910cbdd337 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -19,7 +19,6 @@ #include "Canvas.h" #include "LayerUpdateQueue.h" #include "RenderNode.h" -#include "VectorDrawable.h" #include "renderstate/OffscreenBufferPool.h" #include "utils/FatVector.h" #include "utils/PaintUtils.h" @@ -546,18 +545,6 @@ void FrameBuilder::deferBitmapRectOp(const BitmapRectOp& op) { currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Bitmap); } -void FrameBuilder::deferVectorDrawableOp(const VectorDrawableOp& op) { - const SkBitmap& bitmap = op.vectorDrawable->getBitmapUpdateIfDirty(); - SkPaint* paint = op.vectorDrawable->getPaint(); - const BitmapRectOp* resolvedOp = new (mAllocator) BitmapRectOp(op.unmappedBounds, - op.localMatrix, - op.localClip, - paint, - &bitmap, - Rect(bitmap.width(), bitmap.height())); - deferBitmapRectOp(*resolvedOp); -} - void FrameBuilder::deferCirclePropsOp(const CirclePropsOp& op) { // allocate a temporary oval op (with mAllocator, so it persists until render), so the // renderer doesn't have to handle the RoundRectPropsOp type, and so state baking is simple. diff --git a/libs/hwui/PropertyValuesAnimatorSet.cpp b/libs/hwui/PropertyValuesAnimatorSet.cpp deleted file mode 100644 index eca1afcc54dc..000000000000 --- a/libs/hwui/PropertyValuesAnimatorSet.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#include "PropertyValuesAnimatorSet.h" -#include "RenderNode.h" - -namespace android { -namespace uirenderer { - -void PropertyValuesAnimatorSet::addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, - Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount) { - - PropertyAnimator* animator = new PropertyAnimator(propertyValuesHolder, - interpolator, startDelay, duration, repeatCount); - mAnimators.emplace_back(animator); - setListener(new PropertyAnimatorSetListener(this)); -} - -PropertyValuesAnimatorSet::PropertyValuesAnimatorSet() - : BaseRenderNodeAnimator(1.0f) { - setStartValue(0); - mLastFraction = 0.0f; - setInterpolator(new LinearInterpolator()); -} - -void PropertyValuesAnimatorSet::onFinished(BaseRenderNodeAnimator* animator) { - if (mOneShotListener.get()) { - mOneShotListener->onAnimationFinished(animator); - mOneShotListener = nullptr; - } -} - -float PropertyValuesAnimatorSet::getValue(RenderNode* target) const { - return mLastFraction; -} - -void PropertyValuesAnimatorSet::setValue(RenderNode* target, float value) { - mLastFraction = value; -} - -void PropertyValuesAnimatorSet::onPlayTimeChanged(nsecs_t playTime) { - for (size_t i = 0; i < mAnimators.size(); i++) { - mAnimators[i]->setCurrentPlayTime(playTime); - } -} - -void PropertyValuesAnimatorSet::reset() { - // TODO: implement reset through adding a play state because we need to support reset() even - // during an animation run. -} - -void PropertyValuesAnimatorSet::start(AnimationListener* listener) { - init(); - mOneShotListener = listener; - BaseRenderNodeAnimator::start(); -} - -void PropertyValuesAnimatorSet::reverse(AnimationListener* listener) { -// TODO: implement reverse -} - -void PropertyValuesAnimatorSet::init() { - if (mInitialized) { - return; - } - nsecs_t maxDuration = 0; - for (size_t i = 0; i < mAnimators.size(); i++) { - if (maxDuration < mAnimators[i]->getTotalDuration()) { - maxDuration = mAnimators[i]->getTotalDuration(); - } - } - mDuration = maxDuration; - mInitialized = true; -} - -uint32_t PropertyValuesAnimatorSet::dirtyMask() { - return RenderNode::DISPLAY_LIST; -} - -PropertyAnimator::PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, - nsecs_t startDelay, nsecs_t duration, int repeatCount) - : mPropertyValuesHolder(holder), mInterpolator(interpolator), mStartDelay(startDelay), - mDuration(duration) { - if (repeatCount < 0) { - mRepeatCount = UINT32_MAX; - } else { - mRepeatCount = repeatCount; - } - mTotalDuration = ((nsecs_t) mRepeatCount + 1) * mDuration + mStartDelay; -} - -void PropertyAnimator::setCurrentPlayTime(nsecs_t playTime) { - if (playTime >= mStartDelay && playTime < mTotalDuration) { - nsecs_t currentIterationPlayTime = (playTime - mStartDelay) % mDuration; - mLatestFraction = currentIterationPlayTime / (float) mDuration; - } else if (mLatestFraction < 1.0f && playTime >= mTotalDuration) { - mLatestFraction = 1.0f; - } else { - return; - } - - setFraction(mLatestFraction); -} - -void PropertyAnimator::setFraction(float fraction) { - float interpolatedFraction = mInterpolator->interpolate(mLatestFraction); - mPropertyValuesHolder->setFraction(interpolatedFraction); -} - -void PropertyAnimatorSetListener::onAnimationFinished(BaseRenderNodeAnimator* animator) { - mSet->onFinished(animator); -} - -} -} diff --git a/libs/hwui/PropertyValuesAnimatorSet.h b/libs/hwui/PropertyValuesAnimatorSet.h deleted file mode 100644 index 4c7ce528bb20..000000000000 --- a/libs/hwui/PropertyValuesAnimatorSet.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#pragma once - -#include "Animator.h" -#include "PropertyValuesHolder.h" -#include "Interpolator.h" - -namespace android { -namespace uirenderer { - -class PropertyAnimator { -public: - PropertyAnimator(PropertyValuesHolder* holder, Interpolator* interpolator, nsecs_t startDelay, - nsecs_t duration, int repeatCount); - void setCurrentPlayTime(nsecs_t playTime); - nsecs_t getTotalDuration() { - return mTotalDuration; - } - void setFraction(float fraction); - -private: - std::unique_ptr<PropertyValuesHolder> mPropertyValuesHolder; - std::unique_ptr<Interpolator> mInterpolator; - nsecs_t mStartDelay; - nsecs_t mDuration; - uint32_t mRepeatCount; - nsecs_t mTotalDuration; - float mLatestFraction = 0.0f; -}; - -class ANDROID_API PropertyValuesAnimatorSet : public BaseRenderNodeAnimator { -public: - friend class PropertyAnimatorSetListener; - PropertyValuesAnimatorSet(); - - void start(AnimationListener* listener); - void reverse(AnimationListener* listener); - void reset(); - - void addPropertyAnimator(PropertyValuesHolder* propertyValuesHolder, - Interpolator* interpolators, int64_t startDelays, - nsecs_t durations, int repeatCount); - virtual uint32_t dirtyMask(); - -protected: - virtual float getValue(RenderNode* target) const override; - virtual void setValue(RenderNode* target, float value) override; - virtual void onPlayTimeChanged(nsecs_t playTime) override; - -private: - void init(); - void onFinished(BaseRenderNodeAnimator* animator); - // Listener set from outside - sp<AnimationListener> mOneShotListener; - std::vector< std::unique_ptr<PropertyAnimator> > mAnimators; - float mLastFraction = 0.0f; - bool mInitialized = false; -}; - -class PropertyAnimatorSetListener : public AnimationListener { -public: - PropertyAnimatorSetListener(PropertyValuesAnimatorSet* set) : mSet(set) {} - virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) override; - -private: - PropertyValuesAnimatorSet* mSet; -}; - -} // namespace uirenderer -} // namespace android diff --git a/libs/hwui/PropertyValuesHolder.cpp b/libs/hwui/PropertyValuesHolder.cpp deleted file mode 100644 index 8f837f6048d6..000000000000 --- a/libs/hwui/PropertyValuesHolder.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#include "PropertyValuesHolder.h" - -#include "utils/VectorDrawableUtils.h" - -#include <utils/Log.h> - -namespace android { -namespace uirenderer { - -using namespace VectorDrawable; - -float PropertyValuesHolder::getValueFromData(float fraction) { - if (mDataSource.size() == 0) { - LOG_ALWAYS_FATAL("No data source is defined"); - return 0; - } - if (fraction <= 0.0f) { - return mDataSource.front(); - } - if (fraction >= 1.0f) { - return mDataSource.back(); - } - - fraction *= mDataSource.size() - 1; - int lowIndex = floor(fraction); - fraction -= lowIndex; - - float value = mDataSource[lowIndex] * (1.0f - fraction) - + mDataSource[lowIndex + 1] * fraction; - return value; -} - -void GroupPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; - if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); - } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; - } - mGroup->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); - mFullPath->setColorPropertyValue(mPropertyId, animatedValue); -} - -void FullPathPropertyValuesHolder::setFraction(float fraction) { - float animatedValue; - if (mDataSource.size() > 0) { - animatedValue = getValueFromData(fraction); - } else { - animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; - } - mFullPath->setPropertyValue(mPropertyId, animatedValue); -} - -void PathDataPropertyValuesHolder::setFraction(float fraction) { - VectorDrawableUtils::interpolatePaths(&mPathData, mStartValue, mEndValue, fraction); - mPath->setPathData(mPathData); -} - -void RootAlphaPropertyValuesHolder::setFraction(float fraction) { - float animatedValue = mStartValue * (1 - fraction) + mEndValue * fraction; - mTree->setRootAlpha(animatedValue); -} - -} // namepace uirenderer -} // namespace android diff --git a/libs/hwui/PropertyValuesHolder.h b/libs/hwui/PropertyValuesHolder.h deleted file mode 100644 index b905faef104c..000000000000 --- a/libs/hwui/PropertyValuesHolder.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2016 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. - */ - -#pragma once - -#include "VectorDrawable.h" - -#include <SkColor.h> - -namespace android { -namespace uirenderer { - -/** - * PropertyValues holder contains data needed to change a property of a Vector Drawable object. - * When a fraction in [0f, 1f] is provided, the holder will calculate an interpolated value based - * on its start and end value, and set the new value on the VectorDrawble's corresponding property. - */ -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; -}; - -class ANDROID_API GroupPropertyValuesHolder : public PropertyValuesHolder { -public: - GroupPropertyValuesHolder(VectorDrawable::Group* ptr, int propertyId, float startValue, - float endValue) - : mGroup(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue){ - } - void setFraction(float fraction) override; -private: - VectorDrawable::Group* mGroup; - int mPropertyId; - float mStartValue; - float mEndValue; -}; - -class ANDROID_API FullPathColorPropertyValuesHolder : public PropertyValuesHolder { -public: - FullPathColorPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, int32_t startValue, - int32_t endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; - 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 { -public: - FullPathPropertyValuesHolder(VectorDrawable::FullPath* ptr, int propertyId, float startValue, - float endValue) - : mFullPath(ptr) - , mPropertyId(propertyId) - , mStartValue(startValue) - , mEndValue(endValue) {}; - void setFraction(float fraction) override; -private: - VectorDrawable::FullPath* mFullPath; - int mPropertyId; - float mStartValue; - float mEndValue; -}; - -class ANDROID_API PathDataPropertyValuesHolder : public PropertyValuesHolder { -public: - PathDataPropertyValuesHolder(VectorDrawable::Path* ptr, PathData* startValue, - PathData* endValue) - : mPath(ptr) - , mStartValue(*startValue) - , mEndValue(*endValue) {}; - void setFraction(float fraction) override; -private: - VectorDrawable::Path* mPath; - PathData mPathData; - PathData mStartValue; - PathData mEndValue; -}; - -class ANDROID_API RootAlphaPropertyValuesHolder : public PropertyValuesHolder { -public: - RootAlphaPropertyValuesHolder(VectorDrawable::Tree* tree, float startValue, float endValue) - : mTree(tree) - , mStartValue(startValue) - , mEndValue(endValue) {} - void setFraction(float fraction) override; -private: - VectorDrawable::Tree* mTree; - float mStartValue; - float mEndValue; -}; -} -} diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h index bb26e2ec67a8..593d690f2b43 100644 --- a/libs/hwui/RecordedOp.h +++ b/libs/hwui/RecordedOp.h @@ -17,7 +17,6 @@ #ifndef ANDROID_HWUI_RECORDED_OP_H #define ANDROID_HWUI_RECORDED_OP_H -#include "RecordedOp.h" #include "font/FontUtil.h" #include "Matrix.h" #include "Rect.h" @@ -40,10 +39,6 @@ class OffscreenBuffer; class RenderNode; struct Vertex; -namespace VectorDrawable { -class Tree; -} - /** * Authoritative op list, used for generating the op ID enum, ID based LUTS, and * the functions to which they dispatch. Parameter macros are executed for each op, @@ -80,7 +75,6 @@ class Tree; PRE_RENDER_OP_FN(EndLayerOp) \ PRE_RENDER_OP_FN(BeginUnclippedLayerOp) \ PRE_RENDER_OP_FN(EndUnclippedLayerOp) \ - PRE_RENDER_OP_FN(VectorDrawableOp) \ \ RENDER_ONLY_OP_FN(ShadowOp) \ RENDER_ONLY_OP_FN(LayerOp) \ @@ -331,13 +325,6 @@ struct RoundRectPropsOp : RecordedOp { const float* ry; }; -struct VectorDrawableOp : RecordedOp { - VectorDrawableOp(VectorDrawable::Tree* tree, BASE_PARAMS_PAINTLESS) - : SUPER_PAINTLESS(VectorDrawableOp) - , vectorDrawable(tree) {} - VectorDrawable::Tree* vectorDrawable; -}; - /** * Real-time, dynamic-lit shadow. * diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp index 16929b8ac8ee..2387962cc795 100644 --- a/libs/hwui/RecordingCanvas.cpp +++ b/libs/hwui/RecordingCanvas.cpp @@ -19,7 +19,6 @@ #include "DeferredLayerUpdater.h" #include "RecordedOp.h" #include "RenderNode.h" -#include "VectorDrawable.h" namespace android { namespace uirenderer { @@ -396,6 +395,7 @@ void RecordingCanvas::drawCircle( &x->value, &y->value, &radius->value)); } + void RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { addOp(new (alloc()) OvalOp( Rect(left, top, right, bottom), @@ -422,15 +422,6 @@ void RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { refPaint(&paint), refPath(&path))); } -void RecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) { - mDisplayList->ref(tree); - addOp(new (alloc()) VectorDrawableOp( - tree, - Rect(tree->getBounds()), - *(mState.currentSnapshot()->transform), - getRecordedClip())); -} - // Bitmap-based void RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) { save(SaveFlags::Matrix); diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h index cc14e6111cec..375760f2dd81 100644 --- a/libs/hwui/RecordingCanvas.h +++ b/libs/hwui/RecordingCanvas.h @@ -175,8 +175,6 @@ public: const uint16_t* indices, int indexCount, const SkPaint& paint) override { /* RecordingCanvas does not support drawVertices(); ignore */ } - virtual void drawVectorDrawable(VectorDrawableRoot* tree) override; - // Bitmap-based virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) override; virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp index bd4442dc378d..d320a410bc84 100644 --- a/libs/hwui/SkiaCanvas.cpp +++ b/libs/hwui/SkiaCanvas.cpp @@ -32,8 +32,6 @@ #include <SkTLazy.h> #include <SkTemplates.h> -#include "VectorDrawable.h" - #include <memory> namespace android { @@ -155,7 +153,6 @@ public: float hOffset, float vOffset, const SkPaint& paint) override; virtual bool drawTextAbsolutePos() const override { return true; } - virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override; virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left, uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right, @@ -745,14 +742,6 @@ void SkiaCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& chu NinePatch::Draw(mCanvas, bounds, bitmap, chunk, paint, nullptr); } -void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) { - const SkBitmap& bitmap = vectorDrawable->getBitmapUpdateIfDirty(); - SkRect bounds = vectorDrawable->getBounds(); - drawBitmap(bitmap, 0, 0, bitmap.width(), bitmap.height(), - bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, - vectorDrawable->getPaint()); -} - // ---------------------------------------------------------------------------- // Canvas draw operations: Text // ---------------------------------------------------------------------------- diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp index 541c799f0149..1cf15ac01154 100644 --- a/libs/hwui/VectorDrawable.cpp +++ b/libs/hwui/VectorDrawable.cpp @@ -138,7 +138,18 @@ void Path::setPath(const char* pathStr, size_t strLength) { } FullPath::FullPath(const FullPath& path) : Path(path) { - mProperties = path.mProperties; + mStrokeWidth = path.mStrokeWidth; + mStrokeColor = path.mStrokeColor; + mStrokeAlpha = path.mStrokeAlpha; + mFillColor = path.mFillColor; + mFillAlpha = path.mFillAlpha; + mTrimPathStart = path.mTrimPathStart; + mTrimPathEnd = path.mTrimPathEnd; + mTrimPathOffset = path.mTrimPathOffset; + mStrokeMiterLimit = path.mStrokeMiterLimit; + mStrokeLineCap = path.mStrokeLineCap; + mStrokeLineJoin = path.mStrokeLineJoin; + SkRefCnt_SafeAssign(mStrokeGradient, path.mStrokeGradient); SkRefCnt_SafeAssign(mFillGradient, path.mFillGradient); } @@ -148,7 +159,7 @@ const SkPath& FullPath::getUpdatedPath() { return mTrimmedSkPath; } Path::getUpdatedPath(); - if (mProperties.trimPathStart != 0.0f || mProperties.trimPathEnd != 1.0f) { + if (mTrimPathStart != 0.0f || mTrimPathEnd != 1.0f) { applyTrim(); return mTrimmedSkPath; } else { @@ -159,14 +170,14 @@ const SkPath& FullPath::getUpdatedPath() { void FullPath::updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin) { - mProperties.strokeWidth = strokeWidth; - mProperties.strokeColor = strokeColor; - mProperties.strokeAlpha = strokeAlpha; - mProperties.fillColor = fillColor; - mProperties.fillAlpha = fillAlpha; - mProperties.strokeMiterLimit = strokeMiterLimit; - mProperties.strokeLineCap = strokeLineCap; - mProperties.strokeLineJoin = strokeLineJoin; + mStrokeWidth = strokeWidth; + mStrokeColor = strokeColor; + mStrokeAlpha = strokeAlpha; + mFillColor = fillColor; + mFillAlpha = fillAlpha; + mStrokeMiterLimit = strokeMiterLimit; + mStrokeLineCap = SkPaint::Cap(strokeLineCap); + mStrokeLineJoin = SkPaint::Join(strokeLineJoin); // If any trim property changes, mark trim dirty and update the trim path setTrimPathStart(trimPathStart); @@ -184,12 +195,12 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str // Draw path's fill, if fill color or gradient is valid bool needsFill = false; if (mFillGradient != nullptr) { - mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.fillAlpha)); + mPaint.setColor(applyAlpha(SK_ColorBLACK, mFillAlpha)); SkShader* newShader = mFillGradient->newWithLocalMatrix(matrix); mPaint.setShader(newShader); needsFill = true; - } else if (mProperties.fillColor != SK_ColorTRANSPARENT) { - mPaint.setColor(applyAlpha(mProperties.fillColor, mProperties.fillAlpha)); + } else if (mFillColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mFillColor, mFillAlpha)); needsFill = true; } @@ -202,21 +213,21 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str // Draw path's stroke, if stroke color or gradient is valid bool needsStroke = false; if (mStrokeGradient != nullptr) { - mPaint.setColor(applyAlpha(SK_ColorBLACK, mProperties.strokeAlpha)); + mPaint.setColor(applyAlpha(SK_ColorBLACK, mStrokeAlpha)); SkShader* newShader = mStrokeGradient->newWithLocalMatrix(matrix); mPaint.setShader(newShader); needsStroke = true; - } else if (mProperties.strokeColor != SK_ColorTRANSPARENT) { - mPaint.setColor(applyAlpha(mProperties.strokeColor, mProperties.strokeAlpha)); + } else if (mStrokeColor != SK_ColorTRANSPARENT) { + mPaint.setColor(applyAlpha(mStrokeColor, mStrokeAlpha)); needsStroke = true; } if (needsStroke) { mPaint.setStyle(SkPaint::Style::kStroke_Style); mPaint.setAntiAlias(true); - mPaint.setStrokeJoin(SkPaint::Join(mProperties.strokeLineJoin)); - mPaint.setStrokeCap(SkPaint::Cap(mProperties.strokeLineCap)); - mPaint.setStrokeMiter(mProperties.strokeMiterLimit); - mPaint.setStrokeWidth(mProperties.strokeWidth * strokeScale); + mPaint.setStrokeJoin(mStrokeLineJoin); + mPaint.setStrokeCap(mStrokeLineCap); + mPaint.setStrokeMiter(mStrokeMiterLimit); + mPaint.setStrokeWidth(mStrokeWidth * strokeScale); outCanvas->drawPath(renderPath, mPaint); } } @@ -225,14 +236,14 @@ void FullPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float str * Applies trimming to the specified path. */ void FullPath::applyTrim() { - if (mProperties.trimPathStart == 0.0f && mProperties.trimPathEnd == 1.0f) { + if (mTrimPathStart == 0.0f && mTrimPathEnd == 1.0f) { // No trimming necessary. return; } SkPathMeasure measure(mSkPath, false); float len = SkScalarToFloat(measure.getLength()); - float start = len * fmod((mProperties.trimPathStart + mProperties.trimPathOffset), 1.0f); - float end = len * fmod((mProperties.trimPathEnd + mProperties.trimPathOffset), 1.0f); + float start = len * fmod((mTrimPathStart + mTrimPathOffset), 1.0f); + float end = len * fmod((mTrimPathEnd + mTrimPathOffset), 1.0f); mTrimmedSkPath.reset(); if (start > end) { @@ -244,69 +255,76 @@ void FullPath::applyTrim() { mTrimDirty = false; } -REQUIRE_COMPATIBLE_LAYOUT(FullPath::Properties); +inline int putData(int8_t* outBytes, int startIndex, float value) { + int size = sizeof(float); + memcpy(&outBytes[startIndex], &value, size); + return size; +} + +inline int putData(int8_t* outBytes, int startIndex, int value) { + int size = sizeof(int); + memcpy(&outBytes[startIndex], &value, size); + return size; +} + +struct FullPathProperties { + // TODO: Consider storing full path properties in this struct instead of the fields. + float strokeWidth; + SkColor strokeColor; + float strokeAlpha; + SkColor fillColor; + float fillAlpha; + float trimPathStart; + float trimPathEnd; + float trimPathOffset; + int32_t strokeLineCap; + int32_t strokeLineJoin; + float strokeMiterLimit; +}; + +REQUIRE_COMPATIBLE_LAYOUT(FullPathProperties); static_assert(sizeof(float) == sizeof(int32_t), "float is not the same size as int32_t"); static_assert(sizeof(SkColor) == sizeof(int32_t), "SkColor is not the same size as int32_t"); bool FullPath::getProperties(int8_t* outProperties, int length) { - int propertyDataSize = sizeof(Properties); + int propertyDataSize = sizeof(FullPathProperties); if (length != propertyDataSize) { LOG_ALWAYS_FATAL("Properties needs exactly %d bytes, a byte array of size %d is provided", propertyDataSize, length); return false; } - Properties* out = reinterpret_cast<Properties*>(outProperties); - *out = mProperties; + // TODO: consider replacing the property fields with a FullPathProperties struct. + FullPathProperties properties; + properties.strokeWidth = mStrokeWidth; + properties.strokeColor = mStrokeColor; + properties.strokeAlpha = mStrokeAlpha; + properties.fillColor = mFillColor; + properties.fillAlpha = mFillAlpha; + properties.trimPathStart = mTrimPathStart; + properties.trimPathEnd = mTrimPathEnd; + properties.trimPathOffset = mTrimPathOffset; + properties.strokeLineCap = mStrokeLineCap; + properties.strokeLineJoin = mStrokeLineJoin; + properties.strokeMiterLimit = mStrokeMiterLimit; + + memcpy(outProperties, &properties, length); return true; } -void FullPath::setColorPropertyValue(int propertyId, int32_t value) { - Property currentProperty = static_cast<Property>(propertyId); - if (currentProperty == Property::StrokeColor) { - mProperties.strokeColor = value; - } else if (currentProperty == Property::FillColor) { - mProperties.fillColor = value; - } else { - LOG_ALWAYS_FATAL("Error setting color property on FullPath: No valid property with id: %d", - propertyId); - } -} - -void FullPath::setPropertyValue(int propertyId, float value) { - Property property = static_cast<Property>(propertyId); - switch (property) { - case Property::StrokeWidth: - setStrokeWidth(value); - break; - case Property::StrokeAlpha: - setStrokeAlpha(value); - break; - case Property::FillAlpha: - setFillAlpha(value); - break; - case Property::TrimPathStart: - setTrimPathStart(value); - break; - case Property::TrimPathEnd: - setTrimPathEnd(value); - break; - case Property::TrimPathOffset: - setTrimPathOffset(value); - break; - default: - LOG_ALWAYS_FATAL("Invalid property id: %d for animation", propertyId); - break; - } -} - void ClipPath::drawPath(SkCanvas* outCanvas, const SkPath& renderPath, float strokeScale, const SkMatrix& matrix){ outCanvas->clipPath(renderPath, SkRegion::kIntersect_Op); } Group::Group(const Group& group) : Node(group) { - mProperties = group.mProperties; + mRotate = group.mRotate; + mPivotX = group.mPivotX; + mPivotY = group.mPivotY; + mScaleX = group.mScaleX; + mScaleY = group.mScaleY; + mTranslateX = group.mTranslateX; + mTranslateY = group.mTranslateY; } void Group::draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX, @@ -353,11 +371,10 @@ void Group::getLocalMatrix(SkMatrix* outMatrix) { outMatrix->reset(); // TODO: use rotate(mRotate, mPivotX, mPivotY) and scale with pivot point, instead of // translating to pivot for rotating and scaling, then translating back. - outMatrix->postTranslate(-mProperties.pivotX, -mProperties.pivotY); - outMatrix->postScale(mProperties.scaleX, mProperties.scaleY); - outMatrix->postRotate(mProperties.rotate, 0, 0); - outMatrix->postTranslate(mProperties.translateX + mProperties.pivotX, - mProperties.translateY + mProperties.pivotY); + outMatrix->postTranslate(-mPivotX, -mPivotY); + outMatrix->postScale(mScaleX, mScaleY); + outMatrix->postRotate(mRotate, 0, 0); + outMatrix->postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); } void Group::addChild(Node* child) { @@ -371,66 +388,36 @@ bool Group::getProperties(float* outProperties, int length) { propertyCount, length); return false; } - Properties* out = reinterpret_cast<Properties*>(outProperties); - *out = mProperties; - return true; -} - -// TODO: Consider animating the properties as float pointers -float Group::getPropertyValue(int propertyId) const { - Property currentProperty = static_cast<Property>(propertyId); - switch (currentProperty) { - case Property::Rotate: - return mProperties.rotate; - case Property::PivotX: - return mProperties.pivotX; - case Property::PivotY: - return mProperties.pivotY; - case Property::ScaleX: - return mProperties.scaleX; - case Property::ScaleY: - return mProperties.scaleY; - case Property::TranslateX: - return mProperties.translateX; - case Property::TranslateY: - return mProperties.translateY; - default: - LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId); - return 0; + for (int i = 0; i < propertyCount; i++) { + Property currentProperty = static_cast<Property>(i); + switch (currentProperty) { + case Property::Rotate_Property: + outProperties[i] = mRotate; + break; + case Property::PivotX_Property: + outProperties[i] = mPivotX; + break; + case Property::PivotY_Property: + outProperties[i] = mPivotY; + break; + case Property::ScaleX_Property: + outProperties[i] = mScaleX; + break; + case Property::ScaleY_Property: + outProperties[i] = mScaleY; + break; + case Property::TranslateX_Property: + outProperties[i] = mTranslateX; + break; + case Property::TranslateY_Property: + outProperties[i] = mTranslateY; + break; + default: + LOG_ALWAYS_FATAL("Invalid input index: %d", i); + return false; + } } -} - -void Group::setPropertyValue(int propertyId, float value) { - Property currentProperty = static_cast<Property>(propertyId); - switch (currentProperty) { - case Property::Rotate: - mProperties.rotate = value; - break; - case Property::PivotX: - mProperties.pivotX = value; - break; - case Property::PivotY: - mProperties.pivotY = value; - break; - case Property::ScaleX: - mProperties.scaleX = value; - break; - case Property::ScaleY: - mProperties.scaleY = value; - break; - case Property::TranslateX: - mProperties.translateX = value; - break; - case Property::TranslateY: - mProperties.translateY = value; - break; - default: - LOG_ALWAYS_FATAL("Invalid property index: %d", propertyId); - } -} - -bool Group::isValidProperty(int propertyId) { - return propertyId >= 0 && propertyId < static_cast<int>(Property::Count); + return true; } void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, @@ -458,8 +445,6 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, return; } - mPaint.setColorFilter(colorFilter); - int saveCount = outCanvas->save(SaveFlags::MatrixClip); outCanvas->translate(mBounds.fLeft, mBounds.fTop); @@ -473,33 +458,43 @@ void Tree::draw(Canvas* outCanvas, SkColorFilter* colorFilter, // And we use this bound for the destination rect for the drawBitmap, so // we offset to (0, 0); mBounds.offsetTo(0, 0); - createCachedBitmapIfNeeded(scaledWidth, scaledHeight); - outCanvas->drawVectorDrawable(this); + createCachedBitmapIfNeeded(scaledWidth, scaledHeight); + if (!mAllowCaching) { + updateCachedBitmap(scaledWidth, scaledHeight); + } else { + if (!canReuseCache || mCacheDirty) { + updateCachedBitmap(scaledWidth, scaledHeight); + } + } + drawCachedBitmapWithRootAlpha(outCanvas, colorFilter, mBounds); outCanvas->restoreToCount(saveCount); } -SkPaint* Tree::getPaint() { +void Tree::drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter, + const SkRect& originalBounds) { SkPaint* paint; - if (mRootAlpha == 1.0f && mPaint.getColorFilter() == NULL) { + if (mRootAlpha == 1.0f && filter == NULL) { paint = NULL; } else { mPaint.setFilterQuality(kLow_SkFilterQuality); mPaint.setAlpha(mRootAlpha * 255); + mPaint.setColorFilter(filter); paint = &mPaint; } - return paint; + outCanvas->drawBitmap(mCachedBitmap, 0, 0, mCachedBitmap.width(), mCachedBitmap.height(), + originalBounds.fLeft, originalBounds.fTop, originalBounds.fRight, + originalBounds.fBottom, paint); } -const SkBitmap& Tree::getBitmapUpdateIfDirty() { +void Tree::updateCachedBitmap(int width, int height) { mCachedBitmap.eraseColor(SK_ColorTRANSPARENT); SkCanvas outCanvas(mCachedBitmap); - float scaleX = (float) mCachedBitmap.width() / mViewportWidth; - float scaleY = (float) mCachedBitmap.height() / mViewportHeight; + float scaleX = width / mViewportWidth; + float scaleY = height / mViewportHeight; mRootNode->draw(&outCanvas, SkMatrix::I(), scaleX, scaleY); mCacheDirty = false; - return mCachedBitmap; } void Tree::createCachedBitmapIfNeeded(int width, int height) { diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h index f8f1ea62a624..09bdce596a21 100644 --- a/libs/hwui/VectorDrawable.h +++ b/libs/hwui/VectorDrawable.h @@ -18,7 +18,6 @@ #define ANDROID_HWUI_VPATH_H #include "Canvas.h" - #include <SkBitmap.h> #include <SkColor.h> #include <SkCanvas.h> @@ -105,21 +104,6 @@ protected: class ANDROID_API FullPath: public Path { public: - -struct Properties { - float strokeWidth = 0; - SkColor strokeColor = SK_ColorTRANSPARENT; - float strokeAlpha = 1; - SkColor fillColor = SK_ColorTRANSPARENT; - float fillAlpha = 1; - float trimPathStart = 0; - float trimPathEnd = 1; - float trimPathOffset = 0; - int32_t strokeLineCap = SkPaint::Cap::kButt_Cap; - int32_t strokeLineJoin = SkPaint::Join::kMiter_Join; - float strokeMiterLimit = 4; -}; - FullPath(const FullPath& path); // for cloning FullPath(const char* path, size_t strLength) : Path(path, strLength) {} FullPath() : Path() {} @@ -134,58 +118,55 @@ struct Properties { float strokeAlpha, SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin); - // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI float getStrokeWidth() { - return mProperties.strokeWidth; + return mStrokeWidth; } void setStrokeWidth(float strokeWidth) { - mProperties.strokeWidth = strokeWidth; + mStrokeWidth = strokeWidth; } SkColor getStrokeColor() { - return mProperties.strokeColor; + return mStrokeColor; } void setStrokeColor(SkColor strokeColor) { - mProperties.strokeColor = strokeColor; + mStrokeColor = strokeColor; } float getStrokeAlpha() { - return mProperties.strokeAlpha; + return mStrokeAlpha; } void setStrokeAlpha(float strokeAlpha) { - mProperties.strokeAlpha = strokeAlpha; + mStrokeAlpha = strokeAlpha; } SkColor getFillColor() { - return mProperties.fillColor; + return mFillColor; } void setFillColor(SkColor fillColor) { - mProperties.fillColor = fillColor; + mFillColor = fillColor; } float getFillAlpha() { - return mProperties.fillAlpha; + return mFillAlpha; } void setFillAlpha(float fillAlpha) { - mProperties.fillAlpha = fillAlpha; + mFillAlpha = fillAlpha; } float getTrimPathStart() { - return mProperties.trimPathStart; + return mTrimPathStart; } void setTrimPathStart(float trimPathStart) { - VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty); + VD_SET_PROP_WITH_FLAG(mTrimPathStart, trimPathStart, mTrimDirty); } float getTrimPathEnd() { - return mProperties.trimPathEnd; + return mTrimPathEnd; } void setTrimPathEnd(float trimPathEnd) { - VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty); + VD_SET_PROP_WITH_FLAG(mTrimPathEnd, trimPathEnd, mTrimDirty); } float getTrimPathOffset() { - return mProperties.trimPathOffset; + return mTrimPathOffset; } void setTrimPathOffset(float trimPathOffset) { - VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty); + VD_SET_PROP_WITH_FLAG(mTrimPathOffset, trimPathOffset, mTrimDirty); } bool getProperties(int8_t* outProperties, int length); - void setColorPropertyValue(int propertyId, int32_t value); - void setPropertyValue(int propertyId, float value); void setFillGradient(SkShader* fillGradient) { SkRefCnt_SafeAssign(mFillGradient, fillGradient); @@ -201,28 +182,24 @@ protected: float strokeScale, const SkMatrix& matrix) override; private: - enum class Property { - StrokeWidth = 0, - StrokeColor, - StrokeAlpha, - FillColor, - FillAlpha, - TrimPathStart, - TrimPathEnd, - TrimPathOffset, - StrokeLineCap, - StrokeLineJoin, - StrokeMiterLimit, - Count, - }; // Applies trimming to the specified path. void applyTrim(); - Properties mProperties; + float mStrokeWidth = 0; + SkColor mStrokeColor = SK_ColorTRANSPARENT; + float mStrokeAlpha = 1; + SkColor mFillColor = SK_ColorTRANSPARENT; + SkShader* mStrokeGradient = nullptr; + SkShader* mFillGradient = nullptr; + float mFillAlpha = 1; + float mTrimPathStart = 0; + float mTrimPathEnd = 1; + float mTrimPathOffset = 0; bool mTrimDirty = true; + SkPaint::Cap mStrokeLineCap = SkPaint::Cap::kButt_Cap; + SkPaint::Join mStrokeLineJoin = SkPaint::Join::kMiter_Join; + float mStrokeMiterLimit = 4; SkPath mTrimmedSkPath; SkPaint mPaint; - SkShader* mStrokeGradient = nullptr; - SkShader* mFillGradient = nullptr; }; class ANDROID_API ClipPath: public Path { @@ -239,58 +216,49 @@ protected: class ANDROID_API Group: public Node { public: - struct Properties { - float rotate = 0; - float pivotX = 0; - float pivotY = 0; - float scaleX = 1; - float scaleY = 1; - float translateX = 0; - float translateY = 0; - }; Group(const Group& group); Group() {} float getRotation() { - return mProperties.rotate; + return mRotate; } void setRotation(float rotation) { - mProperties.rotate = rotation; + mRotate = rotation; } float getPivotX() { - return mProperties.pivotX; + return mPivotX; } void setPivotX(float pivotX) { - mProperties.pivotX = pivotX; + mPivotX = pivotX; } float getPivotY() { - return mProperties.pivotY; + return mPivotY; } void setPivotY(float pivotY) { - mProperties.pivotY = pivotY; + mPivotY = pivotY; } float getScaleX() { - return mProperties.scaleX; + return mScaleX; } void setScaleX(float scaleX) { - mProperties.scaleX = scaleX; + mScaleX = scaleX; } float getScaleY() { - return mProperties.scaleY; + return mScaleY; } void setScaleY(float scaleY) { - mProperties.scaleY = scaleY; + mScaleY = scaleY; } float getTranslateX() { - return mProperties.translateX; + return mTranslateX; } void setTranslateX(float translateX) { - mProperties.translateX = translateX; + mTranslateX = translateX; } float getTranslateY() { - return mProperties.translateY; + return mTranslateY; } void setTranslateY(float translateY) { - mProperties.translateY = translateY; + mTranslateY = translateY; } virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, float scaleX, float scaleY) override; @@ -300,33 +268,38 @@ public: void addChild(Node* child); void dump() override; bool getProperties(float* outProperties, int length); - float getPropertyValue(int propertyId) const; - void setPropertyValue(int propertyId, float value); - static bool isValidProperty(int propertyId); private: enum class Property { - Rotate = 0, - PivotX, - PivotY, - ScaleX, - ScaleY, - TranslateX, - TranslateY, + Rotate_Property = 0, + PivotX_Property, + PivotY_Property, + ScaleX_Property, + ScaleY_Property, + TranslateX_Property, + TranslateY_Property, // Count of the properties, must be at the end. Count, }; + float mRotate = 0; + float mPivotX = 0; + float mPivotY = 0; + float mScaleX = 1; + float mScaleY = 1; + float mTranslateX = 0; + float mTranslateY = 0; std::vector<Node*> mChildren; - Properties mProperties; }; -class ANDROID_API Tree : public VirtualLightRefBase { +class ANDROID_API Tree { public: Tree(Group* rootNode) : mRootNode(rootNode) {} void draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds, bool needsMirroring, bool canReuseCache); + void drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter, + const SkRect& originalBounds); - const SkBitmap& getBitmapUpdateIfDirty(); + void updateCachedBitmap(int width, int height); void createCachedBitmapIfNeeded(int width, int height); bool canReuseBitmap(int width, int height); void setAllowCaching(bool allowCaching) { @@ -343,10 +316,6 @@ public: mViewportWidth = viewportWidth; mViewportHeight = viewportHeight; } - SkPaint* getPaint(); - const SkRect& getBounds() const { - return mBounds; - } private: // Cap the bitmap size, such that it won't hurt the performance too much |