diff options
14 files changed, 677 insertions, 425 deletions
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java index c2e93a7..d2799e1 100644 --- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.ColorFilter; @@ -41,6 +43,7 @@ import com.android.internal.R; */ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable, Animatable { + private static final String TAG = "AnimatedRotateDrawable"; private AnimatedRotateState mState; private boolean mMutated; @@ -186,6 +189,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); + } + + @Override public void invalidateDrawable(Drawable who) { final Callback callback = getCallback(); if (callback != null) { @@ -254,83 +262,113 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override - public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable); - super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); - final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION; - final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + inflateChildElements(r, parser, attrs, theme); - tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); - final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION; - final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + init(); + } - setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12)); - setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150)); + @Override + public void applyTheme(@Nullable Theme t) { + super.applyTheme(t); - final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0); - Drawable drawable = null; - if (res > 0) { - drawable = r.getDrawable(res, theme); + final AnimatedRotateState state = mState; + if (state == null) { + return; } - a.recycle(); - - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && - (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - - if (type != XmlPullParser.START_TAG) { - continue; + if (state.mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes( + state.mThemeAttrs, R.styleable.AnimatedRotateDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); } + } - if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { - Log.w("drawable", "Bad element under <animated-rotate>: " - + parser .getName()); - } + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); } - if (drawable == null) { - Log.w("drawable", "No drawable specified for <animated-rotate>"); + init(); + } + + private void updateStateFromTypedArray(TypedArray a) { + final AnimatedRotateState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) { + final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX); + state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); } - final AnimatedRotateState rotateState = mState; - rotateState.mDrawable = drawable; - rotateState.mPivotXRel = pivotXRel; - rotateState.mPivotX = pivotX; - rotateState.mPivotYRel = pivotYRel; - rotateState.mPivotY = pivotY; + if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotY)) { + final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY); + state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); + } - init(); + setFramesCount(a.getInt( + R.styleable.AnimatedRotateDrawable_framesCount, state.mFramesCount)); + setFramesDuration(a.getInt( + R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration)); - if (drawable != null) { - drawable.setCallback(this); + final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); } } - @Override - public void applyTheme(Theme t) { - super.applyTheme(t); - + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { final AnimatedRotateState state = mState; - if (state == null) { - return; + + Drawable dr = null; + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type != XmlPullParser.START_TAG) { + continue; + } + + if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { + Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName()); + } } - if (state.mDrawable != null) { - state.mDrawable.applyTheme(t); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); } } - @Override - public boolean canApplyTheme() { - final AnimatedRotateState state = mState; - return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme(); + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <animated-rotate> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); + } } public void setFramesCount(int framesCount) { @@ -362,15 +400,16 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac final static class AnimatedRotateState extends Drawable.ConstantState { Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - boolean mPivotXRel; - float mPivotX; - boolean mPivotYRel; - float mPivotY; - int mFrameDuration; - int mFramesCount; + boolean mPivotXRel = false; + float mPivotX = 0; + boolean mPivotYRel = false; + float mPivotY = 0; + int mFrameDuration = 150; + int mFramesCount = 12; private boolean mCanConstantState; private boolean mCheckedConstantState; @@ -387,6 +426,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection()); mDrawable.setBounds(orig.mDrawable.getBounds()); mDrawable.setLevel(orig.mDrawable.getLevel()); + mThemeAttrs = orig.mThemeAttrs; mPivotXRel = orig.mPivotXRel; mPivotX = orig.mPivotX; mPivotYRel = orig.mPivotYRel; @@ -408,6 +448,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java index 849faec..3b125fd 100644 --- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java @@ -347,24 +347,62 @@ public class AnimatedStateListDrawable extends StateListDrawable { throws XmlPullParserException, IOException { final TypedArray a = obtainAttributes( r, theme, attrs, R.styleable.AnimatedStateListDrawable); - super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); + + inflateChildElements(r, parser, attrs, theme); - final StateListState stateListState = getStateListState(); - stateListState.setVariablePadding(a.getBoolean( - R.styleable.AnimatedStateListDrawable_variablePadding, false)); - stateListState.setConstantSize(a.getBoolean( - R.styleable.AnimatedStateListDrawable_constantSize, false)); - stateListState.setEnterFadeDuration(a.getInt( - R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0)); - stateListState.setExitFadeDuration(a.getInt( - R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0)); + init(); + } + + @Override + public void applyTheme(@Nullable Theme theme) { + super.applyTheme(theme); - setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true)); - setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false)); + final AnimatedStateListState state = mState; + if (state == null || !state.canApplyTheme()) { + return; + } + final TypedArray a = theme.resolveAttributes( + state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable); + updateStateFromTypedArray(a); a.recycle(); + init(); + } + + private void updateStateFromTypedArray(TypedArray a) { + final AnimatedStateListState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mAnimThemeAttrs = a.extractThemeAttrs(); + + state.setVariablePadding(a.getBoolean( + R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding)); + state.setConstantSize(a.getBoolean( + R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize)); + state.setEnterFadeDuration(a.getInt( + R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration)); + state.setExitFadeDuration(a.getInt( + R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration)); + + setDither(a.getBoolean( + R.styleable.AnimatedStateListDrawable_dither, state.mDither)); + setAutoMirrored(a.getBoolean( + R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored)); + } + + private void init() { + onStateChange(getState()); + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { int type; final int innerDepth = parser.getDepth() + 1; @@ -386,8 +424,6 @@ public class AnimatedStateListDrawable extends StateListDrawable { parseTransition(r, parser, attrs, theme); } } - - onStateChange(getState()); } private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser, @@ -507,6 +543,8 @@ public class AnimatedStateListDrawable extends StateListDrawable { private static final int REVERSE_SHIFT = 32; private static final int REVERSE_MASK = 0x1; + int[] mAnimThemeAttrs; + final LongSparseLongArray mTransitions; final SparseIntArray mStateIds; @@ -515,6 +553,7 @@ public class AnimatedStateListDrawable extends StateListDrawable { super(orig, owner, res); if (orig != null) { + mAnimThemeAttrs = orig.mAnimThemeAttrs; mTransitions = orig.mTransitions.clone(); mStateIds = orig.mStateIds.clone(); } else { @@ -566,6 +605,11 @@ public class AnimatedStateListDrawable extends StateListDrawable { } @Override + public boolean canApplyTheme() { + return mAnimThemeAttrs != null || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new AnimatedStateListDrawable(this, null); } diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java index a904067..e65dbaf 100644 --- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java @@ -316,9 +316,8 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mAnimatedVectorState != null - && mAnimatedVectorState.mVectorDrawable != null - && mAnimatedVectorState.mVectorDrawable.canApplyTheme(); + return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme()) + || super.canApplyTheme(); } @Override @@ -374,6 +373,12 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable { } @Override + public boolean canApplyTheme() { + return (mVectorDrawable != null && mVectorDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new AnimatedVectorDrawable(this, null); } diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java index c730a20..a8b6c94 100644 --- a/graphics/java/android/graphics/drawable/AnimationDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import java.io.IOException; import org.xmlpull.v1.XmlPullParser; @@ -271,27 +273,25 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - TypedArray a = obtainAttributes(r, theme, attrs, - com.android.internal.R.styleable.AnimationDrawable); - - super.inflateWithAttributes(r, parser, a, - com.android.internal.R.styleable.AnimationDrawable_visible); - - mAnimationState.setVariablePadding(a.getBoolean( - com.android.internal.R.styleable.AnimationDrawable_variablePadding, false)); - - mAnimationState.mOneShot = a.getBoolean( - com.android.internal.R.styleable.AnimationDrawable_oneshot, false); + inflateChildElements(r, parser, attrs, theme); - a.recycle(); + setFrame(0, true, false); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + TypedArray a; int type; final int innerDepth = parser.getDepth()+1; int depth; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT && - ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (type != XmlPullParser.START_TAG) { continue; } @@ -300,17 +300,15 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An continue; } - a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem); - int duration = a.getInt( - com.android.internal.R.styleable.AnimationDrawableItem_duration, -1); + a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem); + + final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1); if (duration < 0) { - throw new XmlPullParserException( - parser.getPositionDescription() + throw new XmlPullParserException(parser.getPositionDescription() + ": <item> tag requires a 'duration' attribute"); } - int drawableRes = a.getResourceId( - com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0); + + final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0); a.recycle(); @@ -322,9 +320,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An // Empty } if (type != XmlPullParser.START_TAG) { - throw new XmlPullParserException(parser.getPositionDescription() + - ": <item> tag requires a 'drawable' attribute or child tag" + - " defining a drawable"); + throw new XmlPullParserException(parser.getPositionDescription() + + ": <item> tag requires a 'drawable' attribute or child tag" + + " defining a drawable"); } dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } @@ -334,8 +332,14 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An dr.setCallback(this); } } + } - setFrame(0, true, false); + private void updateStateFromTypedArray(TypedArray a) { + mAnimationState.mVariablePadding = a.getBoolean( + R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding); + + mAnimationState.mOneShot = a.getBoolean( + R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot); } @Override @@ -357,7 +361,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An private final static class AnimationState extends DrawableContainerState { private int[] mDurations; - private boolean mOneShot; + private boolean mOneShot = false; AnimationState(AnimationState orig, AnimationDrawable owner, Resources res) { diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java index 669cef2..f80a5f4 100644 --- a/graphics/java/android/graphics/drawable/ClipDrawable.java +++ b/graphics/java/android/graphics/drawable/ClipDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -49,7 +51,7 @@ import java.io.IOException; * @attr ref android.R.styleable#ClipDrawable_drawable */ public class ClipDrawable extends Drawable implements Drawable.Callback { - private ClipState mClipState; + private ClipState mState; private final Rect mTmpRect = new Rect(); public static final int HORIZONTAL = 1; @@ -67,9 +69,9 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { public ClipDrawable(Drawable drawable, int gravity, int orientation) { this(null, null); - mClipState.mDrawable = drawable; - mClipState.mGravity = gravity; - mClipState.mOrientation = orientation; + mState.mDrawable = drawable; + mState.mGravity = gravity; + mState.mOrientation = orientation; if (drawable != null) { drawable.setCallback(this); @@ -81,19 +83,22 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { throws XmlPullParserException, IOException { super.inflate(r, parser, attrs, theme); - int type; - - TypedArray a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.ClipDrawable); + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable); - int orientation = a.getInt( - com.android.internal.R.styleable.ClipDrawable_clipOrientation, - HORIZONTAL); - int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT); - Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable); + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); a.recycle(); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; + int type; final int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -103,35 +108,68 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - if (dr == null) { - throw new IllegalArgumentException("No drawable specified for <clip>"); + if (dr != null) { + mState.mDrawable = dr; + dr.setCallback(this); } + } + + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <clip> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); + } + } + + private void updateStateFromTypedArray(TypedArray a) { + final ClipState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); - mClipState.mDrawable = dr; - mClipState.mOrientation = orientation; - mClipState.mGravity = g; + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); - dr.setCallback(this); + state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation); + state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity); + + final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); + } } @Override public void applyTheme(Theme t) { super.applyTheme(t); - final ClipState state = mClipState; + final ClipState state = mState; if (state == null) { return; } - if (state.mDrawable != null) { + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { state.mDrawable.applyTheme(t); } } @Override public boolean canApplyTheme() { - final ClipState state = mClipState; - return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme(); + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } // overrides from Drawable.Callback @@ -165,78 +203,78 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mClipState.mChangingConfigurations - | mClipState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { // XXX need to adjust padding! - return mClipState.mDrawable.getPadding(padding); + return mState.mDrawable.getPadding(padding); } @Override public boolean setVisible(boolean visible, boolean restart) { - mClipState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mClipState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mClipState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mClipState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mClipState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mClipState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } @Override public int getOpacity() { - return mClipState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mClipState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - return mClipState.mDrawable.setState(state); + return mState.mDrawable.setState(state); } @Override protected boolean onLevelChange(int level) { - mClipState.mDrawable.setLevel(level); + mState.mDrawable.setLevel(level); invalidateSelf(); return true; } @Override protected void onBoundsChange(Rect bounds) { - mClipState.mDrawable.setBounds(bounds); + mState.mDrawable.setBounds(bounds); } @Override public void draw(Canvas canvas) { - if (mClipState.mDrawable.getLevel() == 0) { + if (mState.mDrawable.getLevel() == 0) { return; } @@ -244,41 +282,41 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { final Rect bounds = getBounds(); int level = getLevel(); int w = bounds.width(); - final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth(); - if ((mClipState.mOrientation & HORIZONTAL) != 0) { + final int iw = 0; //mState.mDrawable.getIntrinsicWidth(); + if ((mState.mOrientation & HORIZONTAL) != 0) { w -= (w - iw) * (10000 - level) / 10000; } int h = bounds.height(); - final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight(); - if ((mClipState.mOrientation & VERTICAL) != 0) { + final int ih = 0; //mState.mDrawable.getIntrinsicHeight(); + if ((mState.mOrientation & VERTICAL) != 0) { h -= (h - ih) * (10000 - level) / 10000; } final int layoutDirection = getLayoutDirection(); - Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection); + Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection); if (w > 0 && h > 0) { canvas.save(); canvas.clipRect(r); - mClipState.mDrawable.draw(canvas); + mState.mDrawable.draw(canvas); canvas.restore(); } } @Override public int getIntrinsicWidth() { - return mClipState.mDrawable.getIntrinsicWidth(); + return mState.mDrawable.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { - return mClipState.mDrawable.getIntrinsicHeight(); + return mState.mDrawable.getIntrinsicHeight(); } @Override public ConstantState getConstantState() { - if (mClipState.canConstantState()) { - mClipState.mChangingConfigurations = getChangingConfigurations(); - return mClipState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -286,14 +324,14 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { /** @hide */ @Override public void setLayoutDirection(int layoutDirection) { - mClipState.mDrawable.setLayoutDirection(layoutDirection); + mState.mDrawable.setLayoutDirection(layoutDirection); super.setLayoutDirection(layoutDirection); } @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - mClipState.mDrawable.mutate(); + mState.mDrawable.mutate(); mMutated = true; } return this; @@ -304,21 +342,26 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { */ public void clearMutated() { super.clearMutated(); - mClipState.mDrawable.clearMutated(); + mState.mDrawable.clearMutated(); mMutated = false; } final static class ClipState extends ConstantState { - Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - int mOrientation; - int mGravity; + + Drawable mDrawable; + + int mOrientation = HORIZONTAL; + int mGravity = Gravity.LEFT; private boolean mCheckedConstantState; private boolean mCanConstantState; ClipState(ClipState orig, ClipDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -335,6 +378,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new ClipDrawable(this, null); } @@ -360,7 +409,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { } private ClipDrawable(ClipState state, Resources res) { - mClipState = new ClipState(state, this, res); + mState = new ClipState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index a903288..326490f 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -600,11 +600,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { Drawable[] mDrawables; int mNumChildren; - boolean mVariablePadding; + boolean mVariablePadding = false; boolean mPaddingChecked; Rect mConstantPadding; - boolean mConstantSize; + boolean mConstantSize = false; boolean mComputedConstantSize; int mConstantWidth; int mConstantHeight; @@ -625,8 +625,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mMutated; int mLayoutDirection; - int mEnterFadeDuration; - int mExitFadeDuration; + int mEnterFadeDuration = 0; + int mExitFadeDuration = 0; boolean mAutoMirrored; diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java index 47e0e46..1458238 100644 --- a/graphics/java/android/graphics/drawable/GradientDrawable.java +++ b/graphics/java/android/graphics/drawable/GradientDrawable.java @@ -1089,7 +1089,7 @@ public class GradientDrawable extends Drawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mGradientState != null && mGradientState.canApplyTheme(); + return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme(); } private void applyThemeChildElements(Theme t) { @@ -1632,7 +1632,7 @@ public class GradientDrawable extends Drawable { public boolean canApplyTheme() { return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null || mAttrSolid != null || mAttrStroke != null || mAttrCorners != null - || mAttrPadding != null; + || mAttrPadding != null || super.canApplyTheme(); } @Override diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java index f1800e5..b88d9e6 100644 --- a/graphics/java/android/graphics/drawable/InsetDrawable.java +++ b/graphics/java/android/graphics/drawable/InsetDrawable.java @@ -55,7 +55,8 @@ import java.io.IOException; public class InsetDrawable extends Drawable implements Drawable.Callback { private final Rect mTmpRect = new Rect(); - private InsetState mInsetState; + private final InsetState mState; + private boolean mMutated; /*package*/ InsetDrawable() { @@ -70,11 +71,11 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { int insetRight, int insetBottom) { this(null, null); - mInsetState.mDrawable = drawable; - mInsetState.mInsetLeft = insetLeft; - mInsetState.mInsetTop = insetTop; - mInsetState.mInsetRight = insetRight; - mInsetState.mInsetBottom = insetBottom; + mState.mDrawable = drawable; + mState.mInsetLeft = insetLeft; + mState.mInsetTop = insetTop; + mState.mInsetRight = insetRight; + mState.mInsetBottom = insetBottom; if (drawable != null) { drawable.setCallback(this); @@ -87,11 +88,20 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable); super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible); - mInsetState.mDrawable = null; + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); + a.recycle(); + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { // Load inner XML elements. - if (mInsetState.mDrawable == null) { + if (mState.mDrawable == null) { int type; while ((type=parser.next()) == XmlPullParser.TEXT) { } @@ -102,26 +112,23 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { + "child tag defining a drawable"); } final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme); - mInsetState.mDrawable = dr; + mState.mDrawable = dr; dr.setCallback(this); } - - verifyRequiredAttributes(a); - a.recycle(); } private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { // If we're not waiting on a theme, verify required attributes. - if (mInsetState.mDrawable == null && (mInsetState.mThemeAttrs == null - || mInsetState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) { - throw new XmlPullParserException(a.getPositionDescription() + - ": <inset> tag requires a 'drawable' attribute or " + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <inset> tag requires a 'drawable' attribute or " + "child tag defining a drawable"); } } private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { - final InsetState state = mInsetState; + final InsetState state = mState; // Account for any configuration changes. state.mChangingConfigurations |= a.getChangingConfigurations(); @@ -169,7 +176,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { public void applyTheme(Theme t) { super.applyTheme(t); - final InsetState state = mInsetState; + final InsetState state = mState; if (state == null) { return; } @@ -193,7 +200,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mInsetState != null && mInsetState.canApplyTheme(); + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } @Override @@ -222,112 +229,112 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { @Override public void draw(Canvas canvas) { - mInsetState.mDrawable.draw(canvas); + mState.mDrawable.draw(canvas); } @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mInsetState.mChangingConfigurations - | mInsetState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { - boolean pad = mInsetState.mDrawable.getPadding(padding); + boolean pad = mState.mDrawable.getPadding(padding); - padding.left += mInsetState.mInsetLeft; - padding.right += mInsetState.mInsetRight; - padding.top += mInsetState.mInsetTop; - padding.bottom += mInsetState.mInsetBottom; + padding.left += mState.mInsetLeft; + padding.right += mState.mInsetRight; + padding.top += mState.mInsetTop; + padding.bottom += mState.mInsetBottom; - return pad || (mInsetState.mInsetLeft | mInsetState.mInsetRight | - mInsetState.mInsetTop | mInsetState.mInsetBottom) != 0; + return pad || (mState.mInsetLeft | mState.mInsetRight | + mState.mInsetTop | mState.mInsetBottom) != 0; } /** @hide */ @Override public Insets getOpticalInsets() { final Insets contentInsets = super.getOpticalInsets(); - return Insets.of(contentInsets.left + mInsetState.mInsetLeft, - contentInsets.top + mInsetState.mInsetTop, - contentInsets.right + mInsetState.mInsetRight, - contentInsets.bottom + mInsetState.mInsetBottom); + return Insets.of(contentInsets.left + mState.mInsetLeft, + contentInsets.top + mState.mInsetTop, + contentInsets.right + mState.mInsetRight, + contentInsets.bottom + mState.mInsetBottom); } @Override public void setHotspot(float x, float y) { - mInsetState.mDrawable.setHotspot(x, y); + mState.mDrawable.setHotspot(x, y); } @Override public void setHotspotBounds(int left, int top, int right, int bottom) { - mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom); + mState.mDrawable.setHotspotBounds(left, top, right, bottom); } /** @hide */ @Override public void getHotspotBounds(Rect outRect) { - mInsetState.mDrawable.getHotspotBounds(outRect); + mState.mDrawable.getHotspotBounds(outRect); } @Override public boolean setVisible(boolean visible, boolean restart) { - mInsetState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mInsetState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mInsetState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mInsetState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mInsetState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mInsetState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } /** {@hide} */ @Override public void setLayoutDirection(int layoutDirection) { - mInsetState.mDrawable.setLayoutDirection(layoutDirection); + mState.mDrawable.setLayoutDirection(layoutDirection); } @Override public int getOpacity() { - return mInsetState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mInsetState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - boolean changed = mInsetState.mDrawable.setState(state); + boolean changed = mState.mDrawable.setState(state); onBoundsChange(getBounds()); return changed; } @Override protected boolean onLevelChange(int level) { - return mInsetState.mDrawable.setLevel(level); + return mState.mDrawable.setLevel(level); } @Override @@ -335,36 +342,36 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { final Rect r = mTmpRect; r.set(bounds); - r.left += mInsetState.mInsetLeft; - r.top += mInsetState.mInsetTop; - r.right -= mInsetState.mInsetRight; - r.bottom -= mInsetState.mInsetBottom; + r.left += mState.mInsetLeft; + r.top += mState.mInsetTop; + r.right -= mState.mInsetRight; + r.bottom -= mState.mInsetBottom; - mInsetState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); + mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); } @Override public int getIntrinsicWidth() { - return mInsetState.mDrawable.getIntrinsicWidth() - + mInsetState.mInsetLeft + mInsetState.mInsetRight; + return mState.mDrawable.getIntrinsicWidth() + + mState.mInsetLeft + mState.mInsetRight; } @Override public int getIntrinsicHeight() { - return mInsetState.mDrawable.getIntrinsicHeight() - + mInsetState.mInsetTop + mInsetState.mInsetBottom; + return mState.mDrawable.getIntrinsicHeight() + + mState.mInsetTop + mState.mInsetBottom; } @Override public void getOutline(@NonNull Outline outline) { - mInsetState.mDrawable.getOutline(outline); + mState.mDrawable.getOutline(outline); } @Override public ConstantState getConstantState() { - if (mInsetState.canConstantState()) { - mInsetState.mChangingConfigurations = getChangingConfigurations(); - return mInsetState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -372,7 +379,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - mInsetState.mDrawable.mutate(); + mState.mDrawable.mutate(); mMutated = true; } return this; @@ -383,7 +390,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { */ public void clearMutated() { super.clearMutated(); - mInsetState.mDrawable.clearMutated(); + mState.mDrawable.clearMutated(); mMutated = false; } @@ -391,7 +398,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { * Returns the drawable wrapped by this InsetDrawable. May be null. */ public Drawable getDrawable() { - return mInsetState.mDrawable; + return mState.mDrawable; } final static class InsetState extends ConstantState { @@ -400,13 +407,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { Drawable mDrawable; - int mInsetLeft; - int mInsetTop; - int mInsetRight; - int mInsetBottom; + int mInsetLeft = 0; + int mInsetTop = 0; + int mInsetRight = 0; + int mInsetBottom = 0; - boolean mCheckedConstantState; - boolean mCanConstantState; + private boolean mCheckedConstantState; + private boolean mCanConstantState; InsetState(InsetState orig, InsetDrawable owner, Resources res) { if (orig != null) { @@ -430,6 +437,12 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new InsetDrawable(this, null); } @@ -444,12 +457,6 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { return mChangingConfigurations; } - @Override - public boolean canApplyTheme() { - return super.canApplyTheme() || mThemeAttrs != null - || mDrawable != null && mDrawable.canApplyTheme(); - } - boolean canConstantState() { if (!mCheckedConstantState) { mCanConstantState = mDrawable.getConstantState() != null; @@ -461,7 +468,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback { } private InsetDrawable(InsetState state, Resources res) { - mInsetState = new InsetState(state, this, res); + mState = new InsetState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index 5107e10..689d225 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -275,7 +275,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mLayerState != null && mLayerState.canApplyTheme(); + return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme(); } /** @@ -1020,7 +1020,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public boolean canApplyTheme() { - if (mThemeAttrs != null) { + if (mThemeAttrs != null || super.canApplyTheme()) { return true; } diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 316139b..e658279 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -473,7 +473,7 @@ public class RippleDrawable extends LayerDrawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mState != null && mState.canApplyTheme(); + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } @Override diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java index 3f75bc3..9208a0a 100644 --- a/graphics/java/android/graphics/drawable/RotateDrawable.java +++ b/graphics/java/android/graphics/drawable/RotateDrawable.java @@ -31,7 +31,6 @@ import android.content.res.TypedArray; import android.content.res.Resources.Theme; import android.util.TypedValue; import android.util.AttributeSet; -import android.util.Log; import java.io.IOException; @@ -314,6 +313,11 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); + } + + @Override public void invalidateDrawable(Drawable who) { final Callback callback = getCallback(); if (callback != null) { @@ -401,100 +405,101 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, - com.android.internal.R.styleable.RotateDrawable); - - super.inflateWithAttributes(r, parser, a, - com.android.internal.R.styleable.RotateDrawable_visible); - - TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX); - final boolean pivotXRel; - final float pivotX; - if (tv == null) { - pivotXRel = true; - pivotX = 0.5f; - } else { - pivotXRel = tv.type == TypedValue.TYPE_FRACTION; - pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); - } + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible); - tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY); - final boolean pivotYRel; - final float pivotY; - if (tv == null) { - pivotYRel = true; - pivotY = 0.5f; - } else { - pivotYRel = tv.type == TypedValue.TYPE_FRACTION; - pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); - } + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); + a.recycle(); + } - final float fromDegrees = a.getFloat( - com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f); - final float toDegrees = a.getFloat( - com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f); + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); - final int res = a.getResourceId( - com.android.internal.R.styleable.RotateDrawable_drawable, 0); - Drawable drawable = null; - if (res > 0) { - drawable = r.getDrawable(res, theme); + final RotateState state = mState; + if (state == null) { + return; } - a.recycle(); + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } - final int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && - (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); + } + } + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; + int type; + final int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type != XmlPullParser.START_TAG) { continue; } - - if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) { - Log.w("drawable", "Bad element under <rotate>: " - + parser .getName()); - } + dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - if (drawable == null) { - Log.w("drawable", "No drawable specified for <rotate>"); + if (dr != null) { + mState.mDrawable = dr; + dr.setCallback(this); } + } - final RotateState st = mState; - st.mDrawable = drawable; - st.mPivotXRel = pivotXRel; - st.mPivotX = pivotX; - st.mPivotYRel = pivotYRel; - st.mPivotY = pivotY; - st.mFromDegrees = fromDegrees; - st.mCurrentDegrees = fromDegrees; - st.mToDegrees = toDegrees; - - if (drawable != null) { - drawable.setCallback(this); + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <rotate> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); } } - @Override - public void applyTheme(Theme t) { - super.applyTheme(t); - + private void updateStateFromTypedArray(TypedArray a) { final RotateState state = mState; - if (state == null) { - return; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + if (a.hasValue(R.styleable.RotateDrawable_pivotX)) { + final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX); + state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); } - if (state.mDrawable != null) { - state.mDrawable.applyTheme(t); + if (a.hasValue(R.styleable.RotateDrawable_pivotY)) { + final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY); + state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION; + state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); } - } - @Override - public boolean canApplyTheme() { - final RotateState state = mState; - return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme(); + state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees); + state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees); + + final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); + } } @Override @@ -521,25 +526,28 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { * rotations at the same time. */ final static class RotateState extends Drawable.ConstantState { - Drawable mDrawable; - + int[] mThemeAttrs; int mChangingConfigurations; - boolean mPivotXRel; - float mPivotX; - boolean mPivotYRel; - float mPivotY; + Drawable mDrawable; - float mFromDegrees; - float mToDegrees; + boolean mPivotXRel = true; + float mPivotX = 0.5f; + boolean mPivotYRel = true; + float mPivotY = 0.5f; - float mCurrentDegrees; + float mFromDegrees = 0.0f; + float mToDegrees = 360.0f; + + float mCurrentDegrees = 0.0f; - private boolean mCanConstantState; private boolean mCheckedConstantState; + private boolean mCanConstantState; - public RotateState(RotateState orig, RotateDrawable owner, Resources res) { + RotateState(RotateState orig, RotateDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -553,13 +561,20 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { mPivotX = orig.mPivotX; mPivotYRel = orig.mPivotYRel; mPivotY = orig.mPivotY; - mFromDegrees = mCurrentDegrees = orig.mFromDegrees; + mFromDegrees = orig.mFromDegrees; mToDegrees = orig.mToDegrees; - mCanConstantState = mCheckedConstantState = true; + mCurrentDegrees = orig.mCurrentDegrees; + mCheckedConstantState = mCanConstantState = true; } } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new RotateDrawable(this, null); } diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java index 9a5b8fb..fbe38b4 100644 --- a/graphics/java/android/graphics/drawable/ScaleDrawable.java +++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java @@ -16,6 +16,8 @@ package android.graphics.drawable; +import com.android.internal.R; + import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -47,7 +49,7 @@ import java.io.IOException; * @attr ref android.R.styleable#ScaleDrawable_drawable */ public class ScaleDrawable extends Drawable implements Drawable.Callback { - private ScaleState mScaleState; + private ScaleState mState; private boolean mMutated; private final Rect mTmpRect = new Rect(); @@ -58,10 +60,10 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) { this(null, null); - mScaleState.mDrawable = drawable; - mScaleState.mGravity = gravity; - mScaleState.mScaleWidth = scaleWidth; - mScaleState.mScaleHeight = scaleHeight; + mState.mDrawable = drawable; + mState.mGravity = gravity; + mState.mScaleWidth = scaleWidth; + mState.mScaleHeight = scaleHeight; if (drawable != null) { drawable.setCallback(this); @@ -72,18 +74,18 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { * Returns the drawable scaled by this ScaleDrawable. */ public Drawable getDrawable() { - return mScaleState.mDrawable; + return mState.mDrawable; } - private static float getPercent(TypedArray a, int name) { - String s = a.getString(name); + private static float getPercent(TypedArray a, int name, float defaultValue) { + final String s = a.getString(name); if (s != null) { if (s.endsWith("%")) { String f = s.substring(0, s.length() - 1); return Float.parseFloat(f) / 100.0f; } } - return -1; + return defaultValue; } @Override @@ -91,20 +93,48 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { throws XmlPullParserException, IOException { super.inflate(r, parser, attrs, theme); - int type; - - TypedArray a = obtainAttributes( - r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable); + final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable); - float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth); - float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight); - int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT); - boolean min = a.getBoolean( - com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false); - Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable); + // Reset mDrawable to preserve old multiple-inflate behavior. This is + // silly, but we have CTS tests that rely on it. + mState.mDrawable = null; + updateStateFromTypedArray(a); + inflateChildElements(r, parser, attrs, theme); + verifyRequiredAttributes(a); a.recycle(); + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); + + final ScaleState state = mState; + if (state == null) { + return; + } + + if (state.mThemeAttrs == null) { + final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable); + try { + updateStateFromTypedArray(a); + verifyRequiredAttributes(a); + } catch (XmlPullParserException e) { + throw new RuntimeException(e); + } finally { + a.recycle(); + } + } + if (state.mDrawable != null && state.mDrawable.canApplyTheme()) { + state.mDrawable.applyTheme(t); + } + } + + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + Drawable dr = null; + int type; final int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { @@ -114,38 +144,49 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - if (dr == null) { - throw new IllegalArgumentException("No drawable specified for <scale>"); - } - - mScaleState.mDrawable = dr; - mScaleState.mScaleWidth = sw; - mScaleState.mScaleHeight = sh; - mScaleState.mGravity = g; - mScaleState.mUseIntrinsicSizeAsMin = min; if (dr != null) { + mState.mDrawable = dr; dr.setCallback(this); } } - @Override - public void applyTheme(Theme t) { - super.applyTheme(t); - - final ScaleState state = mScaleState; - if (state == null) { - return; + private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException { + // If we're not waiting on a theme, verify required attributes. + if (mState.mDrawable == null && (mState.mThemeAttrs == null + || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) { + throw new XmlPullParserException(a.getPositionDescription() + + ": <scale> tag requires a 'drawable' attribute or " + + "child tag defining a drawable"); } + } - if (state.mDrawable != null) { - state.mDrawable.applyTheme(t); + private void updateStateFromTypedArray(TypedArray a) { + final ScaleState state = mState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mScaleWidth = getPercent( + a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth); + state.mScaleHeight = getPercent( + a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight); + state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT); + state.mUseIntrinsicSizeAsMin = a.getBoolean( + R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false); + + final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable); + if (dr != null) { + state.mDrawable = dr; + dr.setCallback(this); } } @Override public boolean canApplyTheme() { - final ScaleState state = mScaleState; - return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme(); + return (mState != null && mState.canApplyTheme()) || super.canApplyTheme(); } // overrides from Drawable.Callback @@ -172,74 +213,74 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override public void draw(Canvas canvas) { - if (mScaleState.mDrawable.getLevel() != 0) - mScaleState.mDrawable.draw(canvas); + if (mState.mDrawable.getLevel() != 0) + mState.mDrawable.draw(canvas); } @Override public int getChangingConfigurations() { return super.getChangingConfigurations() - | mScaleState.mChangingConfigurations - | mScaleState.mDrawable.getChangingConfigurations(); + | mState.mChangingConfigurations + | mState.mDrawable.getChangingConfigurations(); } @Override public boolean getPadding(Rect padding) { // XXX need to adjust padding! - return mScaleState.mDrawable.getPadding(padding); + return mState.mDrawable.getPadding(padding); } @Override public boolean setVisible(boolean visible, boolean restart) { - mScaleState.mDrawable.setVisible(visible, restart); + mState.mDrawable.setVisible(visible, restart); return super.setVisible(visible, restart); } @Override public void setAlpha(int alpha) { - mScaleState.mDrawable.setAlpha(alpha); + mState.mDrawable.setAlpha(alpha); } @Override public int getAlpha() { - return mScaleState.mDrawable.getAlpha(); + return mState.mDrawable.getAlpha(); } @Override public void setColorFilter(ColorFilter cf) { - mScaleState.mDrawable.setColorFilter(cf); + mState.mDrawable.setColorFilter(cf); } @Override public void setTintList(ColorStateList tint) { - mScaleState.mDrawable.setTintList(tint); + mState.mDrawable.setTintList(tint); } @Override public void setTintMode(Mode tintMode) { - mScaleState.mDrawable.setTintMode(tintMode); + mState.mDrawable.setTintMode(tintMode); } @Override public int getOpacity() { - return mScaleState.mDrawable.getOpacity(); + return mState.mDrawable.getOpacity(); } @Override public boolean isStateful() { - return mScaleState.mDrawable.isStateful(); + return mState.mDrawable.isStateful(); } @Override protected boolean onStateChange(int[] state) { - boolean changed = mScaleState.mDrawable.setState(state); + boolean changed = mState.mDrawable.setState(state); onBoundsChange(getBounds()); return changed; } @Override protected boolean onLevelChange(int level) { - mScaleState.mDrawable.setLevel(level); + mState.mDrawable.setLevel(level); onBoundsChange(getBounds()); invalidateSelf(); return true; @@ -248,41 +289,41 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override protected void onBoundsChange(Rect bounds) { final Rect r = mTmpRect; - final boolean min = mScaleState.mUseIntrinsicSizeAsMin; + final boolean min = mState.mUseIntrinsicSizeAsMin; int level = getLevel(); int w = bounds.width(); - if (mScaleState.mScaleWidth > 0) { - final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0; - w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000); + if (mState.mScaleWidth > 0) { + final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0; + w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000); } int h = bounds.height(); - if (mScaleState.mScaleHeight > 0) { - final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0; - h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000); + if (mState.mScaleHeight > 0) { + final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0; + h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000); } final int layoutDirection = getLayoutDirection(); - Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection); + Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection); if (w > 0 && h > 0) { - mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); + mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom); } } @Override public int getIntrinsicWidth() { - return mScaleState.mDrawable.getIntrinsicWidth(); + return mState.mDrawable.getIntrinsicWidth(); } @Override public int getIntrinsicHeight() { - return mScaleState.mDrawable.getIntrinsicHeight(); + return mState.mDrawable.getIntrinsicHeight(); } @Override public ConstantState getConstantState() { - if (mScaleState.canConstantState()) { - mScaleState.mChangingConfigurations = getChangingConfigurations(); - return mScaleState; + if (mState.canConstantState()) { + mState.mChangingConfigurations = getChangingConfigurations(); + return mState; } return null; } @@ -290,7 +331,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { - mScaleState.mDrawable.mutate(); + mState.mDrawable.mutate(); mMutated = true; } return this; @@ -301,23 +342,28 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { */ public void clearMutated() { super.clearMutated(); - mScaleState.mDrawable.clearMutated(); + mState.mDrawable.clearMutated(); mMutated = false; } final static class ScaleState extends ConstantState { - Drawable mDrawable; + int[] mThemeAttrs; int mChangingConfigurations; - float mScaleWidth; - float mScaleHeight; - int mGravity; - boolean mUseIntrinsicSizeAsMin; + + Drawable mDrawable; + + float mScaleWidth = 1.0f; + float mScaleHeight = 1.0f; + int mGravity = Gravity.LEFT; + boolean mUseIntrinsicSizeAsMin = false; private boolean mCheckedConstantState; private boolean mCanConstantState; ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) { if (orig != null) { + mThemeAttrs = orig.mThemeAttrs; + mChangingConfigurations = orig.mChangingConfigurations; if (res != null) { mDrawable = orig.mDrawable.getConstantState().newDrawable(res); } else { @@ -336,6 +382,12 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme()) + || super.canApplyTheme(); + } + + @Override public Drawable newDrawable() { return new ScaleDrawable(this, null); } @@ -361,7 +413,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { } private ScaleDrawable(ScaleState state, Resources res) { - mScaleState = new ScaleState(state, this, res); + mState = new ScaleState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index a299b3c..963943b 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -117,26 +117,48 @@ public class StateListDrawable extends DrawableContainer { @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { - final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable); + super.inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_visible); + updateStateFromTypedArray(a); + a.recycle(); - super.inflateWithAttributes(r, parser, a, - R.styleable.StateListDrawable_visible); - - mStateListState.setVariablePadding(a.getBoolean( - R.styleable.StateListDrawable_variablePadding, false)); - mStateListState.setConstantSize(a.getBoolean( - R.styleable.StateListDrawable_constantSize, false)); - mStateListState.setEnterFadeDuration(a.getInt( - R.styleable.StateListDrawable_enterFadeDuration, 0)); - mStateListState.setExitFadeDuration(a.getInt( - R.styleable.StateListDrawable_exitFadeDuration, 0)); + inflateChildElements(r, parser, attrs, theme); - setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER)); - setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false)); + onStateChange(getState()); + } - a.recycle(); + /** + * Updates the constant state from the values in the typed array. + */ + private void updateStateFromTypedArray(TypedArray a) { + final StateListState state = mStateListState; + + // Account for any configuration changes. + state.mChangingConfigurations |= a.getChangingConfigurations(); + + // Extract the theme attributes, if any. + state.mThemeAttrs = a.extractThemeAttrs(); + + state.mVariablePadding = a.getBoolean( + R.styleable.StateListDrawable_variablePadding, state.mVariablePadding); + state.mConstantSize = a.getBoolean( + R.styleable.StateListDrawable_constantSize, state.mConstantSize); + state.mEnterFadeDuration = a.getInt( + R.styleable.StateListDrawable_enterFadeDuration, state.mEnterFadeDuration); + state.mExitFadeDuration = a.getInt( + R.styleable.StateListDrawable_exitFadeDuration, state.mExitFadeDuration); + state.mDither = a.getBoolean( + R.styleable.StateListDrawable_dither, state.mDither); + state.mAutoMirrored = a.getBoolean( + R.styleable.StateListDrawable_autoMirrored, state.mAutoMirrored); + } + /** + * Inflates child elements from XML. + */ + private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, + Theme theme) throws XmlPullParserException, IOException { + final StateListState state = mStateListState; final int innerDepth = parser.getDepth() + 1; int type; int depth; @@ -185,10 +207,8 @@ public class StateListDrawable extends DrawableContainer { dr = Drawable.createFromXmlInner(r, parser, attrs, theme); } - mStateListState.addStateSet(states, dr); + state.addStateSet(states, dr); } - - onStateChange(getState()); } StateListState getStateListState() { @@ -282,6 +302,7 @@ public class StateListDrawable extends DrawableContainer { } static class StateListState extends DrawableContainerState { + int[] mThemeAttrs; int[][] mStateSets; StateListState(StateListState orig, StateListDrawable owner, Resources res) { @@ -298,7 +319,11 @@ public class StateListDrawable extends DrawableContainer { mStateSets[i] = set.clone(); } } + + mThemeAttrs = orig.mThemeAttrs; + mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length); } else { + mThemeAttrs = null; mStateSets = new int[getCapacity()][]; } } @@ -331,6 +356,11 @@ public class StateListDrawable extends DrawableContainer { } @Override + public boolean canApplyTheme() { + return mThemeAttrs != null || super.canApplyTheme(); + } + + @Override public void growArray(int oldSize, int newSize) { super.growArray(oldSize, newSize); final int[][] newStateSets = new int[newSize][]; diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java index 848fc53..8b0f635 100644 --- a/graphics/java/android/graphics/drawable/VectorDrawable.java +++ b/graphics/java/android/graphics/drawable/VectorDrawable.java @@ -361,7 +361,7 @@ public class VectorDrawable extends Drawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme(); + return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme(); } @Override @@ -750,8 +750,8 @@ public class VectorDrawable extends Drawable { @Override public boolean canApplyTheme() { - return super.canApplyTheme() || mThemeAttrs != null - || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()); + return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()) + || super.canApplyTheme(); } public VectorDrawableState() { |