GradientDrawable.java revision 6a49ddef62865c1b245ad60a13c334f0ffaf1a5f
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1980756e38882720860db52f1fcc21fa1505a02abfTor Norbyeimport android.annotation.ColorInt;
20519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.content.res.ColorStateList;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
2352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
254d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viveretteimport android.graphics.Color;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.DashPathEffect;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.LinearGradient;
29b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craikimport android.graphics.Outline;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint;
31519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.Path;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
3343027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuff;
3443027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuffColorFilter;
35519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.RadialGradient;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.SweepGradient;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport com.android.internal.R;
4552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
5217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * A Drawable with a color gradient for buttons, backgrounds, etc.
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
54dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code>&lt;shape></code> element. For more
55dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a
56dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_visible
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_shape
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadius
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thickness
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_useLevel
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_width
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_height
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_startColor
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerColor
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_endColor
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_angle
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_type
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerX
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerY
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_gradientRadius
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSolid_color
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_width
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_color
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashWidth
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashGap
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_left
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_top
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_right
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_bottom
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GradientDrawable extends Drawable {
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a rectangle, possibly with rounded corners
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RECTANGLE = 0;
9117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is an ellipse
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    public static final int OVAL = 1;
9617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a line
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LINE = 2;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a ring.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RING = 3;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is linear (default.)
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LINEAR_GRADIENT = 0;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is circular.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RADIAL_GRADIENT = 1;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is a sweep.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SWEEP_GRADIENT  = 2;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
122b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is in pixels. */
123b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_PIXELS = 0;
124b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
125b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is a fraction of the base size. */
126b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_FRACTION = 1;
127b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
128b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is a fraction of the bounds size. */
129b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_FRACTION_PARENT = 2;
130b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
13152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
13252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
13352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GradientState mGradientState;
13517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1366a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik    private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Rect mPadding;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mStrokePaint;   // optional, set by the caller
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ColorFilter mColorFilter;   // optional, set by the caller
14043027b7bca554818cc4223389747d661819d5706Alan Viverette    private PorterDuffColorFilter mTintFilter;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mAlpha = 0xFF;  // modified by the caller
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Path mPath = new Path();
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final RectF mRect = new RectF();
145e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mLayerPaint;    // internal, used if we use saveLayer()
14745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private boolean mGradientIsDirty;
148684385ddde2ac0c26de0862390ad713aff3fb149Romain Guy    private boolean mMutated;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Path mRingPath;
1501041aded2df45094c36831028245fb7c5e9b67b7Romain Guy    private boolean mPathIsDirty = true;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1523aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase    /** Current gradient radius, valid when {@link #mGradientIsDirty} is false. */
153861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    private float mGradientRadius;
154861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Controls how the gradient is oriented relative to the drawable's bounds
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public enum Orientation {
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top to the bottom */
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TOP_BOTTOM,
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top-right to the bottom-left */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TR_BL,
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the right to the left */
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RIGHT_LEFT,
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom-right to the top-left */
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BR_TL,
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom to the top */
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BOTTOM_TOP,
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom-left to the top-right */
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BL_TR,
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the left to the right */
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LEFT_RIGHT,
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top-left to the bottom-right */
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TL_BR,
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GradientDrawable() {
17845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        this(new GradientState(Orientation.TOP_BOTTOM, null), null);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new gradient drawable given an orientation and an array
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of colors for the gradient.
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18580756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public GradientDrawable(Orientation orientation, @ColorInt int[] colors) {
18645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        this(new GradientState(orientation, colors), null);
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPadding(Rect padding) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPadding != null) {
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            padding.set(mPadding);
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.getPadding(padding);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Specify radii for each of the 4 corners. For each corner, the array
2018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * contains 2 values, <code>[X_radius, Y_radius]</code>. The corners are ordered
2028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * top-left, top-right, bottom-right, bottom-left. This property
2038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * is honored only when the shape is of type {@link #RECTANGLE}.</p>
2048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
2058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
2068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
2078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2088bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param radii 4 pairs of X and Y radius for each corner, specified in pixels.
2098bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *              The length of this array must be >= 8
2108bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2118bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
2128bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setCornerRadii(float[])
2138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setShape(int)
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCornerRadii(float[] radii) {
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setCornerRadii(radii);
2171041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
2189891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
22017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Specify radius for the corners of the gradient. If this is > 0, then the
2238bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * drawable is drawn in a round-rectangle, rather than a rectangle. This property
2248bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * is honored only when the shape is of type {@link #RECTANGLE}.</p>
2258bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
2268bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
2278bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
2288bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2298bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param radius The radius in pixels of the corners of the rectangle shape
2308bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
2328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setCornerRadii(float[])
23317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setShape(int)
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCornerRadius(float radius) {
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setCornerRadius(radius);
2371041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
2389891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2408bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2428bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Set the stroke width and color for the drawable. If width is zero,
2438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * then no stroke is drawn.</p>
2448bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
2458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
2468bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
2478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width in pixels of the stroke
2498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param color The color of the stroke
2508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
25217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setStroke(int, int, float, float)
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
25480756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setStroke(int width, @ColorInt int color) {
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setStroke(width, color, 0, 0);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2578bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
2588bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
259a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p>Set the stroke width and color state list for the drawable. If width
260a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * is zero, then no stroke is drawn.</p>
261a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p><strong>Note</strong>: changing this property will affect all instances
262a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * of a drawable loaded from a resource. It is recommended to invoke
263a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * {@link #mutate()} before changing this property.</p>
264a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
265a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param width The width in pixels of the stroke
266a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param colorStateList The color state list of the stroke
267a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
268a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #mutate()
269a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #setStroke(int, ColorStateList, float, float)
270a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     */
271a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public void setStroke(int width, ColorStateList colorStateList) {
272a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        setStroke(width, colorStateList, 0, 0);
273a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
274a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
275a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    /**
2768bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Set the stroke width and color for the drawable. If width is zero,
2778bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * then no stroke is drawn. This method can also be used to dash the stroke.</p>
2788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
2798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
2808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
2818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2828bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width in pixels of the stroke
2838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param color The color of the stroke
28417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
2858bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param dashGap The gap in pixels between dashes
2868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
28817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setStroke(int, int)
2898bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
29080756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) {
29140df78153987409dbf299b84da9784b69029e184Alan Viverette        mGradientState.setStroke(width, ColorStateList.valueOf(color), dashWidth, dashGap);
292a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        setStrokeInternal(width, color, dashWidth, dashGap);
293a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
295a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    /**
296a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p>Set the stroke width and color state list for the drawable. If width
297a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * is zero, then no stroke is drawn. This method can also be used to dash
298a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * the stroke.</p>
299a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p><strong>Note</strong>: changing this property will affect all instances
300a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * of a drawable loaded from a resource. It is recommended to invoke
301a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * {@link #mutate()} before changing this property.</p>
302a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
303a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param width The width in pixels of the stroke
304a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param colorStateList The color state list of the stroke
305a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
306a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param dashGap The gap in pixels between dashes
307a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
308a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #mutate()
309a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #setStroke(int, ColorStateList)
310a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     */
311a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public void setStroke(
312a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
31340df78153987409dbf299b84da9784b69029e184Alan Viverette        mGradientState.setStroke(width, colorStateList, dashWidth, dashGap);
31440df78153987409dbf299b84da9784b69029e184Alan Viverette        final int color;
3157c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        if (colorStateList == null) {
31640df78153987409dbf299b84da9784b69029e184Alan Viverette            color = Color.TRANSPARENT;
3177c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        } else {
3187c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette            final int[] stateSet = getState();
31940df78153987409dbf299b84da9784b69029e184Alan Viverette            color = colorStateList.getColorForState(stateSet, 0);
3207c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        }
32140df78153987409dbf299b84da9784b69029e184Alan Viverette        setStrokeInternal(width, color, dashWidth, dashGap);
322a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
323a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
324a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) {
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStrokePaint == null)  {
3266a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStyle(Paint.Style.STROKE);
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setStrokeWidth(width);
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setColor(color);
33117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        DashPathEffect e = null;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dashWidth > 0) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setPathEffect(e);
3379891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3398bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3408bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3418bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
3428bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the size of the shape drawn by this drawable.</p>
3438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3448bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
3468bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width of the shape used by this drawable
3488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param height The height of the shape used by this drawable
3498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
3518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setGradientType(int)
3528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setSize(int width, int height) {
3541041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mGradientState.setSize(width, height);
3551041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
3569891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3588bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
3608bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the type of shape used to draw the gradient.</p>
3618bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3628bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3638bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
3648bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3658bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param shape The desired shape for this drawable: {@link #LINE},
3668bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *              {@link #OVAL}, {@link #RECTANGLE} or {@link #RING}
3678bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3688bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
3698bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setShape(int shape) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRingPath = null;
3721041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setShape(shape);
3749891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3778bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
3788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the type of gradient used by this drawable..</p>
3798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
3828bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param gradient The type of the gradient: {@link #LINEAR_GRADIENT},
3848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *                 {@link #RADIAL_GRADIENT} or {@link #SWEEP_GRADIENT}
3858bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
3878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientType(int gradient) {
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setGradientType(gradient);
3903aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
3919891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3948bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
39517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * <p>Sets the center location of the gradient. The radius is honored only when
3968bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * the gradient type is set to {@link #RADIAL_GRADIENT} or {@link #SWEEP_GRADIENT}.</p>
3978bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3988bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3998bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
4008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param x The x coordinate of the gradient's center
4028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param y The y coordinate of the gradient's center
4038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
4058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setGradientType(int)
4068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientCenter(float x, float y) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setGradientCenter(x, y);
4093aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4109891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
4148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the radius of the gradient. The radius is honored only when the
4158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * gradient type is set to {@link #RADIAL_GRADIENT}.</p>
4168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
4178bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
4188bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
4198bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4208bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param gradientRadius The radius of the gradient in pixels
4218bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
42317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setGradientType(int)
4248bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientRadius(float gradientRadius) {
426861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        mGradientState.setGradientRadius(gradientRadius, TypedValue.COMPLEX_UNIT_PX);
4273aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4289891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
432861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * Returns the radius of the gradient in pixels. The radius is valid only
433861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * when the gradient type is set to {@link #RADIAL_GRADIENT}.
434861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     *
435861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * @return Radius in pixels.
436861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     */
437861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    public float getGradientRadius() {
438861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        if (mGradientState.mGradient != RADIAL_GRADIENT) {
439861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette            return 0;
440861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        }
441861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
442861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        ensureValidRect();
443861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        return mGradientRadius;
444861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    }
445861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
446861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    /**
4478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets whether or not this drawable will honor its <code>level</code>
4488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * property.</p>
4498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
4508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
4518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
4528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4538bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param useLevel True if this drawable should honor its level, false otherwise
4548bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4558bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
45617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setLevel(int)
45717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #getLevel()
4588bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setUseLevel(boolean useLevel) {
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.mUseLevel = useLevel;
4613aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4629891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
46417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int modulateAlpha(int alpha) {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int scale = mAlpha + (mAlpha >> 7);
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return alpha * scale >> 8;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4708bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
4718bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * Returns the orientation of the gradient defined in this drawable.
4728bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4738bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public Orientation getOrientation() {
4748bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        return mGradientState.mOrientation;
4758bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
4768bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
4778bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
4788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Changes the orientation of the gradient defined in this drawable.</p>
4798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing orientation will affect all instances
4808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
4818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing the orientation.</p>
48217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
4838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param orientation The desired orientation (angle) of the gradient
48417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
48517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #mutate()
4868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public void setOrientation(Orientation orientation) {
4888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        mGradientState.mOrientation = orientation;
4893aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4908bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
4918bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
4928bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
4938bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
494e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Sets the colors used to draw the gradient.
495e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
496e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Each color is specified as an ARGB integer and the array must contain at
497e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * least 2 colors.
498e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
499e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <strong>Note</strong>: changing colors will affect all instances of a
500e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * drawable loaded from a resource. It is recommended to invoke
501e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * {@link #mutate()} before changing the colors.
5028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
503e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @param colors an array containing 2 or more ARGB colors
5048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
50517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColor(int)
5068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
50780756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColors(@ColorInt int[] colors) {
508e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setGradientColors(colors);
5093aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
5108bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
5118bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
5128bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
51416f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette    public void draw(Canvas canvas) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ensureValidRect()) {
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // nothing to draw
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // remember the alpha values, in case we temporarily overwrite them
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // when we modulate them with mAlpha
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevFillAlpha = mFillPaint.getAlpha();
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevStrokeAlpha = mStrokePaint != null ? mStrokePaint.getAlpha() : 0;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the modulate alpha values
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currFillAlpha = modulateAlpha(prevFillAlpha);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
528e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
529e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                mStrokePaint.getStrokeWidth() > 0;
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean haveFill = currFillAlpha > 0;
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final GradientState st = mGradientState;
53243027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter;
53343027b7bca554818cc4223389747d661819d5706Alan Viverette
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  we need a layer iff we're drawing both a fill and stroke, and the
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroke is non-opaque, and our shapetype actually supports
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fill+stroke. Otherwise we can just draw the stroke (if any) on top
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            of the fill (if any) without worrying about blending artifacts.
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
53943027b7bca554818cc4223389747d661819d5706Alan Viverette        final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
54043027b7bca554818cc4223389747d661819d5706Alan Viverette                 currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null);
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  Drawing with a layer is slower than direct drawing, but it
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            allows us to apply paint effects like alpha and colorfilter to
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            the result of multiple separate draws. In our case, if the user
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asks for a non-opaque alpha value (via setAlpha), and we're
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroking, then we need to apply the alpha AFTER we've drawn
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            both the fill and the stroke.
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        */
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLayerPaint == null) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLayerPaint = new Paint();
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
55307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mLayerPaint.setDither(st.mDither);
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayerPaint.setAlpha(mAlpha);
55543027b7bca554818cc4223389747d661819d5706Alan Viverette            mLayerPaint.setColorFilter(colorFilter);
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float rad = mStrokePaint.getStrokeWidth();
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.saveLayer(mRect.left - rad, mRect.top - rad,
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             mRect.right + rad, mRect.bottom + rad,
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             mLayerPaint, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't perform the filter in our individual paints
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // since the layer will do it for us
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setColorFilter(null);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setColorFilter(null);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*  if we're not using a layer, apply the dither/filter to our
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                individual paints
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(currFillAlpha);
57107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mFillPaint.setDither(st.mDither);
57243027b7bca554818cc4223389747d661819d5706Alan Viverette            mFillPaint.setColorFilter(colorFilter);
573e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (colorFilter != null && st.mSolidColors == null) {
574813680780f365648b39873fa26dfae0123d51aedChet Haase                mFillPaint.setColor(mAlpha << 24);
57541c769d9a8858ad20b0a6ed942a1cea19ba59d2dRomain Guy            }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(currStrokeAlpha);
57807c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette                mStrokePaint.setDither(st.mDither);
57943027b7bca554818cc4223389747d661819d5706Alan Viverette                mStrokePaint.setColorFilter(colorFilter);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
582e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (st.mShape) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RECTANGLE:
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mRadiusArray != null) {
586e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(mPath, mFillPaint);
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawPath(mPath, mStrokePaint);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
59161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else if (st.mRadius > 0.0f) {
5924e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // since the caller is only giving us 1 value, we will force
5934e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // it to be square if the rect is too small in one dimension
5944e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // to show it. If we did nothing, Skia would clamp the rad
59561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    // independently along each axis, giving us a thin ellipse
5964e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // if the rect were very wide but not very tall
597b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    float rad = Math.min(st.mRadius,
598b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(mRect.width(), mRect.height()) * 0.5f);
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawRoundRect(mRect, rad, rad, mFillPaint);
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
60361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else {
60443027b7bca554818cc4223389747d661819d5706Alan Viverette                    if (mFillPaint.getColor() != 0 || colorFilter != null ||
605cf8675ee176a375f873792684d38a47f78348dffRomain Guy                            mFillPaint.getShader() != null) {
606cf8675ee176a375f873792684d38a47f78348dffRomain Guy                        canvas.drawRect(mRect, mFillPaint);
607cf8675ee176a375f873792684d38a47f78348dffRomain Guy                    }
60861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    if (haveStroke) {
60961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        canvas.drawRect(mRect, mStrokePaint);
61061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case OVAL:
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawOval(mRect, mFillPaint);
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawOval(mRect, mStrokePaint);
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LINE: {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                RectF r = mRect;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float y = r.centerY();
62271b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                if (haveStroke) {
62371b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                    canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
62471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                }
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RING:
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Path path = buildRing(st);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawPath(path, mFillPaint);
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(path, mStrokePaint);
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
63517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.restore();
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(prevFillAlpha);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(prevStrokeAlpha);
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
645e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
646e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    private void buildPathIfDirty() {
647e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        final GradientState st = mGradientState;
6483aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mPathIsDirty) {
6493aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            ensureValidRect();
650e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.reset();
651e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
6523aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mPathIsDirty = false;
653e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        }
654e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    }
655e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Path buildRing(GradientState st) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = false;
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;
66117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF bounds = new RectF(mRect);
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float x = bounds.width() / 2.0f;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float y = bounds.height() / 2.0f;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float thickness = st.mThickness != -1 ?
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mThickness : bounds.width() / st.mThicknessRatio;
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // inner radius
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius = st.mInnerRadius != -1 ?
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mInnerRadius : bounds.width() / st.mInnerRadiusRatio;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF innerBounds = new RectF(bounds);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        innerBounds.inset(x - radius, y - radius);
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds = new RectF(innerBounds);
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds.inset(-thickness, -thickness);
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath == null) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRingPath = new Path();
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
682b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            mRingPath.reset();
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Path ringPath = mRingPath;
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // arcTo treats the sweep angle mod 360, so check for that, since we
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // think 360 means draw the entire oval
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sweep < 360 && sweep > -360) {
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.setFillType(Path.FillType.EVEN_ODD);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner top
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.moveTo(x + radius, y);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer top
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.lineTo(x + radius + thickness, y);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer arc
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(bounds, 0.0f, sweep, false);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner arc
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(innerBounds, sweep, -sweep, false);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.close();
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // add the entire ovals
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(bounds, Path.Direction.CW);
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(innerBounds, Path.Direction.CCW);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ringPath;
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7088bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
709519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <p>Changes this drawable to use a single color instead of a gradient.</p>
710e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy     * <p><strong>Note</strong>: changing color will affect all instances
7118bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
712e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy     * {@link #mutate()} before changing the color.</p>
7138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
7148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param argb The color used to fill the shape
7158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
7168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
71717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColors(int[])
7188bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
71980756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColor(@ColorInt int argb) {
720e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(ColorStateList.valueOf(argb));
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFillPaint.setColor(argb);
7229891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
725519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    /**
726519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * Changes this drawable to use a single color state list instead of a
7277c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * gradient. Calling this method with a null argument will clear the color
7287c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * and is equivalent to calling {@link #setColor(int)} with the argument
7297c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * {@link Color#TRANSPARENT}.
730519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <p>
731519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <strong>Note</strong>: changing color will affect all instances of a
732519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * drawable loaded from a resource. It is recommended to invoke
733519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * {@link #mutate()} before changing the color.</p>
734519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     *
735519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @param colorStateList The color state list used to fill the shape
736519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @see #mutate()
737519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     */
738519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    public void setColor(ColorStateList colorStateList) {
739e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(colorStateList);
74040df78153987409dbf299b84da9784b69029e184Alan Viverette        final int color;
7417c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        if (colorStateList == null) {
74240df78153987409dbf299b84da9784b69029e184Alan Viverette            color = Color.TRANSPARENT;
7437c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        } else {
74440df78153987409dbf299b84da9784b69029e184Alan Viverette            final int[] stateSet = getState();
74540df78153987409dbf299b84da9784b69029e184Alan Viverette            color = colorStateList.getColorForState(stateSet, 0);
7467c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        }
74740df78153987409dbf299b84da9784b69029e184Alan Viverette        mFillPaint.setColor(color);
74840df78153987409dbf299b84da9784b69029e184Alan Viverette        invalidateSelf();
749519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
750519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
751519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
75212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette    protected boolean onStateChange(int[] stateSet) {
753a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        boolean invalidateSelf = false;
754a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
755a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
756e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        final ColorStateList solidColors = s.mSolidColors;
757e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (solidColors != null) {
758e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int newColor = solidColors.getColorForState(stateSet, 0);
759519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int oldColor = mFillPaint.getColor();
760519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            if (oldColor != newColor) {
761519494e207322581075c8ea884fde9d33bb9209eAlan Viverette                mFillPaint.setColor(newColor);
762616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                invalidateSelf = true;
763a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            }
764a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
765a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
766616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        final Paint strokePaint = mStrokePaint;
767616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        if (strokePaint != null) {
768e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final ColorStateList strokeColors = s.mStrokeColors;
769e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (strokeColors != null) {
770e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int newColor = strokeColors.getColorForState(stateSet, 0);
771e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int oldColor = strokePaint.getColor();
772e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (oldColor != newColor) {
773e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    strokePaint.setColor(newColor);
774616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                    invalidateSelf = true;
775616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                }
776519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            }
777519494e207322581075c8ea884fde9d33bb9209eAlan Viverette        }
778519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
77943027b7bca554818cc4223389747d661819d5706Alan Viverette        if (s.mTint != null && s.mTintMode != null) {
78043027b7bca554818cc4223389747d661819d5706Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode);
78143027b7bca554818cc4223389747d661819d5706Alan Viverette            invalidateSelf = true;
78243027b7bca554818cc4223389747d661819d5706Alan Viverette        }
78343027b7bca554818cc4223389747d661819d5706Alan Viverette
784a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        if (invalidateSelf) {
785a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            invalidateSelf();
786a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            return true;
787a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
788a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
789a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return false;
790519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
791519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
792519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
793519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    public boolean isStateful() {
794a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
795a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return super.isStateful()
796e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mSolidColors != null && s.mSolidColors.isStateful())
797e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mStrokeColors != null && s.mStrokeColors.isStateful())
79843027b7bca554818cc4223389747d661819d5706Alan Viverette                || (s.mTint != null && s.mTint.isStateful());
799519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
800519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getChangingConfigurations() {
803e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
8089891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (alpha != mAlpha) {
8099891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mAlpha = alpha;
8109891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
8119891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
815b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
816b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mAlpha;
817b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
818b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
819b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
82107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        if (dither != mGradientState.mDither) {
82207c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mGradientState.mDither = dither;
8239891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
8249891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
828f4c068b72e2dee2e6944488ef00b64c93217d7e8Alan Viverette    public boolean getDither() {
829f4c068b72e2dee2e6944488ef00b64c93217d7e8Alan Viverette        return mGradientState.mDither;
830f4c068b72e2dee2e6944488ef00b64c93217d7e8Alan Viverette    }
831f4c068b72e2dee2e6944488ef00b64c93217d7e8Alan Viverette
832f4c068b72e2dee2e6944488ef00b64c93217d7e8Alan Viverette    @Override
83338b5f597de96cd892add9017dc810212f549bf68John Spurlock    public ColorFilter getColorFilter() {
83438b5f597de96cd892add9017dc810212f549bf68John Spurlock        return mColorFilter;
83538b5f597de96cd892add9017dc810212f549bf68John Spurlock    }
83638b5f597de96cd892add9017dc810212f549bf68John Spurlock
83738b5f597de96cd892add9017dc810212f549bf68John Spurlock    @Override
838bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik    public void setColorFilter(ColorFilter colorFilter) {
839bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        if (colorFilter != mColorFilter) {
840bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mColorFilter = colorFilter;
8419891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
8429891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
84643027b7bca554818cc4223389747d661819d5706Alan Viverette    public void setTintList(ColorStateList tint) {
84743027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTint = tint;
84843027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
84943027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
85043027b7bca554818cc4223389747d661819d5706Alan Viverette    }
85143027b7bca554818cc4223389747d661819d5706Alan Viverette
85243027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
85343027b7bca554818cc4223389747d661819d5706Alan Viverette    public void setTintMode(PorterDuff.Mode tintMode) {
85443027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTintMode = tintMode;
85543027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
85643027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
85743027b7bca554818cc4223389747d661819d5706Alan Viverette    }
85843027b7bca554818cc4223389747d661819d5706Alan Viverette
85943027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
861888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ?
8620a1c6f021be032f5aecb341c2794efb06c0a8a0dAlan Viverette                PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect r) {
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onBoundsChange(r);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRingPath = null;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
8703aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected boolean onLevelChange(int level) {
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onLevelChange(level);
8763aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8833aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase     * This checks mGradientIsDirty, and if it is true, recomputes both our drawing
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle (mRect) and the gradient itself, since it depends on our
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle too.
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the resulting rectangle is not empty, false otherwise
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean ensureValidRect() {
8893aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mGradientIsDirty) {
8903aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mGradientIsDirty = false;
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect bounds = getBounds();
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float inset = 0;
89417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mStrokePaint != null) {
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inset = mStrokePaint.getStrokeWidth() * 0.5f;
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final GradientState st = mGradientState;
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRect.set(bounds.left + inset, bounds.top + inset,
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                      bounds.right - inset, bounds.bottom - inset);
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
904e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int[] gradientColors = st.mGradientColors;
905e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (gradientColors != null) {
906e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final RectF r = mRect;
907e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final float x0, x1, y0, y1;
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mGradient == LINEAR_GRADIENT) {
9107979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (st.mOrientation) {
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TOP_BOTTOM:
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.bottom;
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TR_BL:
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.bottom;
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case RIGHT_LEFT:
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = y0;
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BR_TL:
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.bottom;
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.top;
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BOTTOM_TOP:
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.top;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BL_TR:
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.top;
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case LEFT_RIGHT:
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = y0;
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    default:/* TL_BR */
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.bottom;
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
947e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            gradientColors, st.mPositions, Shader.TileMode.CLAMP));
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == RADIAL_GRADIENT) {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
952861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    float radius = st.mGradientRadius;
953b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
954b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // Fall back to parent width or height if intrinsic
955b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // size is not specified.
956b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float width = st.mWidth >= 0 ? st.mWidth : r.width();
957b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float height = st.mHeight >= 0 ? st.mHeight : r.height();
958b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        radius *= Math.min(width, height);
959b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    } else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) {
960861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                        radius *= Math.min(r.width(), r.height());
961861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
962b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
963861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    if (st.mUseLevel) {
964861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                        radius *= getLevel() / 10000.0f;
965861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
966b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
967861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mGradientRadius = radius;
968b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
969b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                    if (radius <= 0) {
970b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // We can't have a shader with non-positive radius, so
971b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // let's have a very, very small radius.
972b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                        radius = 0.001f;
973b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    }
974b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
975861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mFillPaint.setShader(new RadialGradient(
976e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP));
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == SWEEP_GRADIENT) {
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
981e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    int[] tempColors = gradientColors;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    float[] tempPositions = null;
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (st.mUseLevel) {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempColors = st.mTempColors;
986e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        final int length = gradientColors.length;
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempColors == null || tempColors.length != length + 1) {
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempColors = st.mTempColors = new int[length + 1];
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
990e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        System.arraycopy(gradientColors, 0, tempColors, 0, length);
991e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        tempColors[length] = gradientColors[length - 1];
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions = st.mTempPositions;
99452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        final float fraction = 1.0f / (length - 1);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempPositions == null || tempPositions.length != length + 1) {
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions = st.mTempPositions = new float[length + 1];
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
99952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        final float level = getLevel() / 10000.0f;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (int i = 0; i < length; i++) {
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions[i] = i * fraction * level;
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions[length] = 1.0f;
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
10074d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                }
10084d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette
10094d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // If we don't have a solid color, the alpha channel must be
10104d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // maxed out so that alpha modulation works correctly.
1011e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (st.mSolidColors == null) {
10124d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                    mFillPaint.setColor(Color.BLACK);
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return !mRect.isEmpty();
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
102052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
102252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawable);
102352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        super.inflateWithAttributes(r, parser, a, R.styleable.GradientDrawable_visible);
102417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        updateStateFromTypedArray(a);
102552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        a.recycle();
102652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
102752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        inflateChildElements(r, parser, attrs, theme);
102852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
102945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(r);
103052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
103152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
103252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
103352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public void applyTheme(Theme t) {
103452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        super.applyTheme(t);
103552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
103652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
103717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state == null) {
103817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            return;
103952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
104052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
104117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state.mThemeAttrs != null) {
104217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            final TypedArray a = t.resolveAttributes(
104317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    state.mThemeAttrs, R.styleable.GradientDrawable);
104417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            updateStateFromTypedArray(a);
104517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            a.recycle();
104617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
104752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
104845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mTint != null && state.mTint.canApplyTheme()) {
1049e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mTint = state.mTint.obtainForTheme(t);
105045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
105145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1052e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) {
1053e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mSolidColors = state.mSolidColors.obtainForTheme(t);
105445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
105545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1056e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) {
1057e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mStrokeColors = state.mStrokeColors.obtainForTheme(t);
105845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
105945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
106017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        applyThemeChildElements(t);
106152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
106245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(t.getResources());
106352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
106452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
106552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
106652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Updates the constant state from the values in the typed array.
106752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
106852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void updateStateFromTypedArray(TypedArray a) {
106952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
107052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
10718e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
10728e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
10738e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
107417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
107517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
107652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
107717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape);
107807c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither);
107952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
108052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (state.mShape == RING) {
108117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mInnerRadius = a.getDimensionPixelSize(
108217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_innerRadius, state.mInnerRadius);
108352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
108417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mInnerRadius == -1) {
108552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mInnerRadiusRatio = a.getFloat(
108617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_innerRadiusRatio, state.mInnerRadiusRatio);
108752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
108852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
108917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mThickness = a.getDimensionPixelSize(
109017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_thickness, state.mThickness);
109152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
109217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mThickness == -1) {
109352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mThicknessRatio = a.getFloat(
109417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_thicknessRatio, state.mThicknessRatio);
109552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
109652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
109717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mUseLevelForShape = a.getBoolean(
109817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape);
109952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
110043027b7bca554818cc4223389747d661819d5706Alan Viverette
110143027b7bca554818cc4223389747d661819d5706Alan Viverette        final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1);
110243027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tintMode != -1) {
110343027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN);
110443027b7bca554818cc4223389747d661819d5706Alan Viverette        }
110543027b7bca554818cc4223389747d661819d5706Alan Viverette
110643027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint);
110743027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tint != null) {
110843027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTint = tint;
110943027b7bca554818cc4223389747d661819d5706Alan Viverette        }
111052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
111152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
111252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
111352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
1114d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
111552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
111652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
111752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void applyThemeChildElements(Theme t) {
111817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
111952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
112017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSize != null) {
112117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
112217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSize, R.styleable.GradientDrawableSize);
112317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSize(a);
112452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
112552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
112652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
112717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrGradient != null) {
112817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
112917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrGradient, R.styleable.GradientDrawableGradient);
113017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            try {
113117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(t.getResources(), a);
113217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } catch (XmlPullParserException e) {
113317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                throw new RuntimeException(e);
113417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } finally {
113517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.recycle();
113617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            }
113752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
113852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
113917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSolid != null) {
114017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
114117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSolid, R.styleable.GradientDrawableSolid);
114217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSolid(a);
114352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
114452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
114552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
114617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrStroke != null) {
114717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
114817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrStroke, R.styleable.GradientDrawableStroke);
114917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableStroke(a);
115052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
115152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
115252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
115317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrCorners != null) {
115417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
115517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrCorners, R.styleable.DrawableCorners);
115617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateDrawableCorners(a);
115752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
115852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
115952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
116017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrPadding != null) {
116117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
116217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrPadding, R.styleable.GradientDrawablePadding);
116317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawablePadding(a);
116452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
116552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
116652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
116752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
116852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
116952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            Theme theme) throws XmlPullParserException, IOException {
117052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        TypedArray a;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1173ed7894352f8addfe3d0da75cc7fe8bc6fef201dcRomain Guy        final int innerDepth = parser.getDepth() + 1;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               && ((depth=parser.getDepth()) >= innerDepth
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       || type != XmlPullParser.END_TAG)) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth) {
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
118552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = parser.getName();
118717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (name.equals("size")) {
118917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSize);
119017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSize(a);
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("gradient")) {
119317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableGradient);
119417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(r, a);
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("solid")) {
119717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSolid);
119817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSolid(a);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("stroke")) {
120117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableStroke);
120217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableStroke(a);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("corners")) {
120517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.DrawableCorners);
120617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateDrawableCorners(a);
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("padding")) {
120917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawablePadding);
121017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawablePadding(a);
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w("drawable", "Bad element under <shape>: " + name);
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
121552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
121652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
121752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
121817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawablePadding(TypedArray a) {
121917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
122052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
12218e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
12228e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
12238e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
122452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
122517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrPadding = a.extractThemeAttrs();
122617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1227982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        if (st.mPadding == null) {
1228982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette            st.mPadding = new Rect();
1229982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        }
1230982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette
123117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final Rect pad = st.mPadding;
123217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        pad.set(a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_left, pad.left),
123317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_top, pad.top),
123417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_right, pad.right),
123517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_bottom, pad.bottom));
123617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        mPadding = pad;
123752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
1238e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
123917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateDrawableCorners(TypedArray a) {
124017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
124117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
12428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
12438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
12448e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
124517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
124617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrCorners = a.extractThemeAttrs();
124717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
124817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int radius = a.getDimensionPixelSize(
124917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.DrawableCorners_radius, (int) st.mRadius);
125052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        setCornerRadius(radius);
125117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
125217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
125317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topLeftRadius = a.getDimensionPixelSize(
125452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topLeftRadius, radius);
125517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topRightRadius = a.getDimensionPixelSize(
125652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topRightRadius, radius);
125717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomLeftRadius = a.getDimensionPixelSize(
125852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomLeftRadius, radius);
125917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomRightRadius = a.getDimensionPixelSize(
126052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomRightRadius, radius);
126152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (topLeftRadius != radius || topRightRadius != radius ||
126252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                bottomLeftRadius != radius || bottomRightRadius != radius) {
126352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // The corner radii are specified in clockwise order (see Path.addRoundRect())
126452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setCornerRadii(new float[] {
126552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topLeftRadius, topLeftRadius,
126652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topRightRadius, topRightRadius,
126752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomRightRadius, bottomRightRadius,
126852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomLeftRadius, bottomLeftRadius
126952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            });
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
127152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
127252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
127317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableStroke(TypedArray a) {
127417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
127517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
12768e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
12778e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
12788e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
12798e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
128017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrStroke = a.extractThemeAttrs();
128117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
12823b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // We have an explicit stroke defined, so the default stroke width
12833b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // must be at least 0 or the current stroke width.
12843b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        final int defaultStrokeWidth = Math.max(0, st.mStrokeWidth);
128552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int width = a.getDimensionPixelSize(
12863b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                R.styleable.GradientDrawableStroke_width, defaultStrokeWidth);
128752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final float dashWidth = a.getDimension(
128817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_dashWidth, st.mStrokeDashWidth);
128917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
129017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        ColorStateList colorStateList = a.getColorStateList(
129117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_color);
129217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList == null) {
1293e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            colorStateList = st.mStrokeColors;
129417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
129517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
129652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (dashWidth != 0.0f) {
129752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final float dashGap = a.getDimension(
129817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawableStroke_dashGap, st.mStrokeDashGap);
129952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList, dashWidth, dashGap);
130052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
130152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList);
130252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
130352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
130452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
130517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSolid(TypedArray a) {
13068e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final GradientState st = mGradientState;
13078e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
13088e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
13098e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
13108e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
13118e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
13128e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mAttrSolid = a.extractThemeAttrs();
131317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
131452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final ColorStateList colorStateList = a.getColorStateList(
131552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableSolid_color);
131617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList != null) {
131717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            setColor(colorStateList);
131817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
131952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
132052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
132117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableGradient(Resources r, TypedArray a)
132252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            throws XmlPullParserException {
132352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState st = mGradientState;
132417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
13258e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
13268e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
13278e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
132817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
132917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrGradient = a.extractThemeAttrs();
133017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
133117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterX = getFloatOrFraction(
133217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerX, st.mCenterX);
133317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterY = getFloatOrFraction(
133417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerY, st.mCenterY);
133517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mUseLevel = a.getBoolean(
133617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_useLevel, st.mUseLevel);
133717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mGradient = a.getInt(
133817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_type, st.mGradient);
133917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
134017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
134152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int startColor = a.getColor(
134252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_startColor, 0);
134352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final boolean hasCenterColor = a.hasValue(
134452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor);
134552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int centerColor = a.getColor(
134652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor, 0);
134752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int endColor = a.getColor(
134852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_endColor, 0);
134952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
135052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (hasCenterColor) {
1351e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[3];
1352e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1353e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = centerColor;
1354e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[2] = endColor;
135517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
135652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions = new float[3];
135752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[0] = 0.0f;
135852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // Since 0.5f is default value, try to take the one that isn't 0.5f
135952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY;
136052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[2] = 1f;
136152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
1362e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[2];
1363e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1364e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = endColor;
136552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
136652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
136752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (st.mGradient == LINEAR_GRADIENT) {
136817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
136952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            angle %= 360;
137052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
137152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (angle % 45 != 0) {
137252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(a.getPositionDescription()
137352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'angle' attribute to "
137452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "be a multiple of 45");
137552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
137652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
137717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            st.mAngle = angle;
137817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
137952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            switch (angle) {
138052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 0:
138152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.LEFT_RIGHT;
138252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
138352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 45:
138452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BL_TR;
138552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
138652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 90:
138752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BOTTOM_TOP;
138852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
138952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 135:
139052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BR_TL;
139152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
139252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 180:
139352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.RIGHT_LEFT;
139452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
139552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 225:
139652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TR_BL;
139752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
139852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 270:
139952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TOP_BOTTOM;
140052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
140152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 315:
140252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TL_BR;
140352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
140452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
140552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
140617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
140752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (tv != null) {
140852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                final float radius;
140952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                final int radiusType;
141052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (tv.type == TypedValue.TYPE_FRACTION) {
141152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getFraction(1.0f, 1.0f);
141252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
141352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT)
141452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                            & TypedValue.COMPLEX_UNIT_MASK;
141552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) {
141652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION_PARENT;
141752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    } else {
141852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION;
141952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
14202efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else if (tv.type == TypedValue.TYPE_DIMENSION) {
142152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getDimension(r.getDisplayMetrics());
142252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
14232efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else {
14242efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radius = tv.getFloat();
14252efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
142652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
142752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
142852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadius = radius;
142952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadiusType = radiusType;
143052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            } else if (st.mGradient == RADIAL_GRADIENT) {
143152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(
143252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        a.getPositionDescription()
143352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'gradientRadius' "
143452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "attribute with radial type");
143552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
143652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
143752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
143852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
143917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSize(TypedArray a) {
144017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
144152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
14428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14448e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
144552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
144617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrSize = a.extractThemeAttrs();
144717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
144817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mWidth = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_width, st.mWidth);
144917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mHeight = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_height, st.mHeight);
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedValue tv = a.peekValue(index);
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float v = defaultValue;
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tv != null) {
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean vIsFraction = tv.type == TypedValue.TYPE_FRACTION;
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v = vIsFraction ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return v;
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
146117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mWidth;
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mHeight;
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
147117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
14746efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mGradientState.mChangingConfigurations = getChangingConfigurations();
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState;
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1478888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    private boolean isOpaqueForState() {
1479888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        if (mGradientState.mStrokeWidth >= 0 && mStrokePaint != null
1480888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette                && !isOpaque(mStrokePaint.getColor())) {
1481888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1482888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1483888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
1484888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        if (!isOpaque(mFillPaint.getColor())) {
1485888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1486888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1487888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
1488888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return true;
1489888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
1490888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
149231ba192dd201df2cad96a8c503f730130ab0d80fChris Craik    public void getOutline(Outline outline) {
1493b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final GradientState st = mGradientState;
1494b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final Rect bounds = getBounds();
1495c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik        // only report non-zero alpha if shape being drawn is opaque
1496888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        outline.setAlpha(st.mOpaqueOverShape && isOpaqueForState() ? (mAlpha / 255.0f) : 0.0f);
1497b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1498b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        switch (st.mShape) {
1499b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            case RECTANGLE:
1500b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadiusArray != null) {
1501e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
1502e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    outline.setConvexPath(mPath);
150331ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                    return;
1504b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
1505e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
1506b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                float rad = 0;
1507b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadius > 0.0f) {
1508b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    // clamp the radius based on width & height, matching behavior in draw()
1509b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    rad = Math.min(st.mRadius,
1510b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(bounds.width(), bounds.height()) * 0.5f);
1511b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
15127979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setRoundRect(bounds, rad);
151331ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
15147979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case OVAL:
15157979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setOval(bounds);
151631ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
15177979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case LINE:
15183b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // Hairlines (0-width stroke) must have a non-empty outline for
15193b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // shadows to draw correctly, so we'll use a very small width.
15203b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float halfStrokeWidth = mStrokePaint == null ?
15213b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                        0.0001f : mStrokePaint.getStrokeWidth() * 0.5f;
15223b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float centerY = bounds.centerY();
15233b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int top = (int) Math.floor(centerY - halfStrokeWidth);
15243b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
1525b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1526e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                outline.setRect(bounds.left, top, bounds.right, bottom);
152731ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
1528b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            default:
152931ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                // TODO: support more complex shapes
1530b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        }
1531b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
1532b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1533b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    @Override
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradientState = new GradientState(mGradientState);
153745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            updateLocalState(null);
15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1543727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
1544727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
1545727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
1546727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
1547727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
1548727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
1549727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
1550727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final static class GradientState extends ConstantState {
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mChangingConfigurations;
15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mShape = RECTANGLE;
15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mGradient = LINEAR_GRADIENT;
155571b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mAngle = 0;
15569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Orientation mOrientation;
1557e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mSolidColors;
1558e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mStrokeColors;
1559e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public int[] mGradientColors;
15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int[] mTempColors; // no need to copy
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mTempPositions; // no need to copy
15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mPositions;
156371b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mStrokeWidth = -1; // if >= 0 use stroking.
156471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashWidth = 0.0f;
156571b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashGap = 0.0f;
156671b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mRadius = 0.0f; // use this if mRadiusArray is null
156771b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float[] mRadiusArray = null;
156871b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public Rect mPadding = null;
15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mWidth = -1;
15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mHeight = -1;
157117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
157217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
157317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mInnerRadius = -1;
157417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mThickness = -1;
157507c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        public boolean mDither = false;
157607c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette
1577969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterX = 0.5f;
1578969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterY = 0.5f;
1579969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mGradientRadius = 0.5f;
1580969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        int mGradientRadiusType = RADIUS_TYPE_PIXELS;
1581969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevel = false;
1582969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevelForShape = true;
1583969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette
1584969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverBounds;
1585969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverShape;
15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
158743027b7bca554818cc4223389747d661819d5706Alan Viverette        ColorStateList mTint = null;
158843027b7bca554818cc4223389747d661819d5706Alan Viverette        PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
158943027b7bca554818cc4223389747d661819d5706Alan Viverette
159052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mThemeAttrs;
159152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSize;
159252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrGradient;
159352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSolid;
159452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrStroke;
159552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrCorners;
159652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrPadding;
159752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1598e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public GradientState(Orientation orientation, int[] gradientColors) {
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOrientation = orientation;
1600e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            setGradientColors(gradientColors);
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public GradientState(GradientState state) {
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mChangingConfigurations = state.mChangingConfigurations;
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShape = state.mShape;
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradient = state.mGradient;
160717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            mAngle = state.mAngle;
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOrientation = state.mOrientation;
1609e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = state.mSolidColors;
1610e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (state.mGradientColors != null) {
1611e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                mGradientColors = state.mGradientColors.clone();
1612562bf17c6c7c5226b2220e27a1543d4a43543d6cPhil Dubach            }
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mPositions != null) {
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPositions = state.mPositions.clone();
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1616e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mStrokeColors = state.mStrokeColors;
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeWidth = state.mStrokeWidth;
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashWidth = state.mStrokeDashWidth;
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashGap = state.mStrokeDashGap;
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = state.mRadius;
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mRadiusArray != null) {
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRadiusArray = state.mRadiusArray.clone();
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mPadding != null) {
1625982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette                mPadding = new Rect(state.mPadding);
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = state.mWidth;
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = state.mHeight;
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInnerRadiusRatio = state.mInnerRadiusRatio;
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mThicknessRatio = state.mThicknessRatio;
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInnerRadius = state.mInnerRadius;
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mThickness = state.mThickness;
163307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mDither = state.mDither;
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterX = state.mCenterX;
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterY = state.mCenterY;
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradientRadius = state.mGradientRadius;
1637b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette            mGradientRadiusType = state.mGradientRadiusType;
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUseLevel = state.mUseLevel;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mUseLevelForShape = state.mUseLevelForShape;
1640c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = state.mOpaqueOverBounds;
1641c3a63c1fbb47f167f6736ad637fd6c6e3ee9d1d8Alan Viverette            mOpaqueOverShape = state.mOpaqueOverShape;
164243027b7bca554818cc4223389747d661819d5706Alan Viverette            mTint = state.mTint;
164343027b7bca554818cc4223389747d661819d5706Alan Viverette            mTintMode = state.mTintMode;
164452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mThemeAttrs = state.mThemeAttrs;
164552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrSize = state.mAttrSize;
164652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrGradient = state.mAttrGradient;
164752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrSolid = state.mAttrSolid;
164852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrStroke = state.mAttrStroke;
164952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrCorners = state.mAttrCorners;
165052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            mAttrPadding = state.mAttrPadding;
165152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
165252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
165352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
165452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
165545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mThemeAttrs != null
165645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSize != null || mAttrGradient != null
165745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSolid != null || mAttrStroke != null
165845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrCorners != null || mAttrPadding != null
165945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mTint != null && mTint.canApplyTheme())
1660e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mStrokeColors != null && mStrokeColors.canApplyTheme())
1661e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mSolidColors != null && mSolidColors.canApplyTheme())
166245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || super.canApplyTheme();
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
166745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return new GradientDrawable(this, null);
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
166917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1671c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        public Drawable newDrawable(Resources res) {
167245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return new GradientDrawable(this, res);
1673c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
167417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1675c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int getChangingConfigurations() {
1677e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mChangingConfigurations
1678e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0)
1679e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0)
1680e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setShape(int shape) {
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShape = shape;
1685e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setGradientType(int gradient) {
16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradient = gradient;
16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setGradientCenter(float x, float y) {
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterX = x;
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterY = y;
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1697e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public void setGradientColors(int[] colors) {
1698e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = colors;
1699e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = null;
1700e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
17018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        }
1702519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
1703e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public void setSolidColors(ColorStateList colors) {
1704e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = null;
1705e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = colors;
1706e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
1707e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
1708e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
1709e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        private void computeOpacity() {
1710c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = false;
1711c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = false;
171239824f685c33f8aabbe9526b4cc79b7411e8b37fRaph Levien
1713e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors != null) {
1714e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                for (int i = 0; i < mGradientColors.length; i++) {
1715e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    if (!isOpaque(mGradientColors[i])) {
1716e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                        return;
1717e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                    }
1718e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                }
1719e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            }
1720e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
172122cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            // An unfilled shape is not opaque over bounds or shape
1722e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors == null && mSolidColors == null) {
172322cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase                return;
172422cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            }
172522cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase
1726c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // Colors are opaque, so opaqueOverShape=true,
1727c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = true;
1728c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // and opaqueOverBounds=true if shape fills bounds
1729c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = mShape == RECTANGLE
1730c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadius <= 0
1731c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadiusArray == null;
1732e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
1733e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
1734e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) {
1735a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            mStrokeWidth = width;
1736e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mStrokeColors = colors;
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashWidth = dashWidth;
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashGap = dashGap;
1739e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadius(float radius) {
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radius < 0) {
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                radius = 0;
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = null;
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1749e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadii(float[] radii) {
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = radii;
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radii == null) {
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRadius = 0;
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1756e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setSize(int width, int height) {
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = width;
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = height;
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1762861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        public void setGradientRadius(float gradientRadius, int type) {
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradientRadius = gradientRadius;
1764b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette            mGradientRadiusType = type;
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1768888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    static boolean isOpaque(int color) {
1769888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return ((color >> 24) & 0xff) == 0xff;
1770888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
1771888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
177252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
177352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Creates a new themed GradientDrawable based on the specified constant state.
177452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * <p>
177552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * The resulting drawable is guaranteed to have a new constant state.
177652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     *
177752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * @param state Constant state from which the drawable inherits
177852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
177945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private GradientDrawable(GradientState state, Resources res) {
178017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        mGradientState = state;
178152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
178245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(res);
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
178545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void updateLocalState(Resources res) {
178645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final GradientState state = mGradientState;
178745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1788e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null) {
1789519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int[] currentState = getState();
1790e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int stateColor = state.mSolidColors.getColorForState(currentState, 0);
1791519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            mFillPaint.setColor(stateColor);
1792e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        } else if (state.mGradientColors == null) {
1793cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // If we don't have a solid color and we don't have a gradient,
1794cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // the app is stroking the shape, set the color to the default
1795cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // value of state.mSolidColor
1796cf8675ee176a375f873792684d38a47f78348dffRomain Guy            mFillPaint.setColor(0);
17974d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette        } else {
17984d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            // Otherwise, make sure the fill alpha is maxed out.
17994d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            mFillPaint.setColor(Color.BLACK);
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
180117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPadding = state.mPadding;
180317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state.mStrokeWidth >= 0) {
18056a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStyle(Paint.Style.STROKE);
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStrokeWidth(state.mStrokeWidth);
180817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1809e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (state.mStrokeColors != null) {
1810083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                final int[] currentState = getState();
1811e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int strokeStateColor = state.mStrokeColors.getColorForState(
1812083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                        currentState, 0);
1813083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                mStrokePaint.setColor(strokeStateColor);
1814083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette            }
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mStrokeDashWidth != 0.0f) {
181717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                final DashPathEffect e = new DashPathEffect(
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0);
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setPathEffect(e);
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18223ad771b384b55bc0b9ee9519f457ea7093bb0b74Alan Viverette
1823daec594370f0e47bf07d0c9c968e3c5dfedf0bb5Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
182445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mGradientIsDirty = true;
182545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
182645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        state.computeOpacity();
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1829