diff options
6 files changed, 130 insertions, 22 deletions
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 438d1fb..0e597d0 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -5271,11 +5271,16 @@ <attr name="viewportWidth" format="float"/> <!-- The height of the canvas the drawing is on. --> <attr name="viewportHeight" format="float"/> + <!-- The name of this vector drawable --> + <attr name="name" /> + <!-- The opacity of the whole vector drawable, as a value between 0 + (completely transparent) and 1 (completely opaque). --> + <attr name="alpha" /> </declare-styleable> <!-- Defines the group used in VectorDrawables. --> <declare-styleable name="VectorDrawableGroup"> - <!-- The Name of this group --> + <!-- The name of this group --> <attr name="name" /> <!-- The amount to rotate the group --> <attr name="rotation" /> @@ -5295,7 +5300,7 @@ <!-- Defines the path used in VectorDrawables. --> <declare-styleable name="VectorDrawablePath"> - <!-- The Name of this path --> + <!-- The name of this path --> <attr name="name" /> <!-- The width a path stroke --> <attr name="strokeWidth" format="float" /> diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 4407a3c..5fd8c79 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -256,21 +256,22 @@ public class VectorDrawable extends Drawable { } if (!mAllowCaching) { - mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height()); + // AnimatedVectorDrawable + if (!mVectorState.hasTranslucentRoot()) { + mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height()); + } else { + mVectorState.createCachedBitmapIfNeeded(bounds); + mVectorState.updateCachedBitmap(bounds); + mVectorState.drawCachedBitmapWithRootAlpha(canvas); + } } else { - Bitmap bitmap = mVectorState.mCachedBitmap; - if (bitmap == null || !mVectorState.canReuseCache(bounds.width(), - bounds.height())) { - bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), - Bitmap.Config.ARGB_8888); - Canvas tmpCanvas = new Canvas(bitmap); - mVectorState.mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height()); - mVectorState.mCachedBitmap = bitmap; - + // Static Vector Drawable case. + mVectorState.createCachedBitmapIfNeeded(bounds); + if (!mVectorState.canReuseCache()) { + mVectorState.updateCachedBitmap(bounds); mVectorState.updateCacheStates(); } - // The bitmap's size is the same as the bounds. - canvas.drawBitmap(bitmap, 0, 0, null); + mVectorState.drawCachedBitmapWithRootAlpha(canvas); } canvas.restoreToCount(saveCount); @@ -492,6 +493,15 @@ public class VectorDrawable extends Drawable { throw new XmlPullParserException(a.getPositionDescription() + "<vector> tag requires height > 0"); } + + final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha, + pathRenderer.getAlpha()); + pathRenderer.setAlpha(alphaInFloat); + + pathRenderer.mRootName = a.getString(R.styleable.VectorDrawable_name); + if (pathRenderer.mRootName != null) { + pathRenderer.mVGTargetsMap.put(pathRenderer.mRootName, pathRenderer); + } } private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs, @@ -646,15 +656,60 @@ public class VectorDrawable extends Drawable { } } - public boolean canReuseCache(int width, int height) { + // TODO: Support colorFilter here. + public void drawCachedBitmapWithRootAlpha(Canvas canvas) { + Paint alphaPaint = getRootAlphaPaint(); + // The bitmap's size is the same as the bounds. + canvas.drawBitmap(mCachedBitmap, 0, 0, alphaPaint); + } + + public boolean hasTranslucentRoot() { + return mVPathRenderer.getRootAlpha() < 255; + } + + /** + * @return null when there is no need for alpha paint. + */ + public Paint getRootAlphaPaint() { + Paint paint = null; + boolean needsAlphaPaint = hasTranslucentRoot(); + if (needsAlphaPaint) { + paint = new Paint(); + paint.setAlpha(mVPathRenderer.getRootAlpha()); + } + return paint; + } + + public void updateCachedBitmap(Rect bounds) { + mCachedBitmap.eraseColor(Color.TRANSPARENT); + Canvas tmpCanvas = new Canvas(mCachedBitmap); + mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height()); + } + + public void createCachedBitmapIfNeeded(Rect bounds) { + if (mCachedBitmap == null || !canReuseBitmap(bounds.width(), + bounds.height())) { + mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), + Bitmap.Config.ARGB_8888); + } + + } + + public boolean canReuseBitmap(int width, int height) { + if (width == mCachedBitmap.getWidth() + && height == mCachedBitmap.getHeight()) { + return true; + } + return false; + } + + public boolean canReuseCache() { if (!mCacheDirty && mCachedThemeAttrs == mThemeAttrs && mCachedTint == mTint && mCachedTintMode == mTintMode && mCachedAutoMirrored == mAutoMirrored - && width == mCachedBitmap.getWidth() - && height == mCachedBitmap.getHeight() - && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { + && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { return true; } return false; @@ -729,7 +784,8 @@ public class VectorDrawable extends Drawable { float mBaseHeight = 0; float mViewportWidth = 0; float mViewportHeight = 0; - private int mRootAlpha = 0xFF; + int mRootAlpha = 0xFF; + String mRootName = null; final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>(); @@ -747,6 +803,17 @@ public class VectorDrawable extends Drawable { return mRootAlpha; } + // setAlpha() and getAlpha() are used mostly for animation purpose, since + // Animator like to use alpha from 0 to 1. + public void setAlpha(float alpha) { + setRootAlpha((int) (alpha * 255)); + } + + @SuppressWarnings("unused") + public float getAlpha() { + return getRootAlpha() / 255.0f; + } + public VPathRenderer(VPathRenderer copy) { mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); mPath = new Path(copy.mPath); @@ -757,6 +824,10 @@ public class VectorDrawable extends Drawable { mViewportHeight = copy.mViewportHeight; mChangingConfigurations = copy.mChangingConfigurations; mRootAlpha = copy.mRootAlpha; + mRootName = copy.mRootName; + if (copy.mRootName != null) { + mVGTargetsMap.put(copy.mRootName, this); + } } public boolean canApplyTheme() { @@ -856,7 +927,7 @@ public class VectorDrawable extends Drawable { } private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h) { - final float scaleX = w / mViewportWidth; + final float scaleX = w / mViewportWidth; final float scaleY = h / mViewportHeight; final float minScale = Math.min(scaleX, scaleY); @@ -1219,7 +1290,7 @@ public class VectorDrawable extends Drawable { /** * Clip path, which only has name and pathData. */ - private static class VClipPath extends VPath{ + private static class VClipPath extends VPath { public VClipPath() { // Empty constructor. } diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml new file mode 100644 index 0000000..1a81866 --- /dev/null +++ b/tests/VectorDrawableTest/res/anim/trim_path_animation06.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 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. +--> + +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <objectAnimator + android:duration="9000" + android:propertyName="alpha" + android:valueFrom="1.0" + android:valueTo="0.0"/> + +</set>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml index 19b82ad..8b0ceda 100644 --- a/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml +++ b/tests/VectorDrawableTest/res/drawable/animation_vector_drawable01.xml @@ -37,5 +37,8 @@ <target android:name="rotationGroup" android:animation="@anim/trim_path_animation04" /> + <target + android:name="rootGroup" + android:animation="@anim/trim_path_animation06" /> </animated-vector>
\ No newline at end of file diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml index 2c8b751..69ae62c 100644 --- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml +++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml @@ -14,10 +14,12 @@ limitations under the License. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" + android:name="rootGroup" android:height="64dp" android:width="64dp" android:viewportHeight="600" - android:viewportWidth="600" > + android:viewportWidth="600" + android:alpha="0.5" > <group android:name="rotationGroup" diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java index f165cde..05bf166 100644 --- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java +++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedVectorDrawableTest.java @@ -31,6 +31,8 @@ public class AnimatedVectorDrawableTest extends Activity implements View.OnClick R.drawable.animation_vector_progress_bar, R.drawable.animation_vector_drawable_favorite, R.drawable.animation_vector_drawable01, + // Duplicate to test constant state. + R.drawable.animation_vector_drawable01, }; @Override |