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;
205f63721a6c2c29e639d8d239834a825c535c034aAlan Viveretteimport android.annotation.IntDef;
21ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viveretteimport android.annotation.NonNull;
2241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viveretteimport android.annotation.Nullable;
23ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viveretteimport android.content.pm.ActivityInfo.Config;
24519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.content.res.ColorStateList;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
2652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme;
2741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viveretteimport android.content.res.TypedArray;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas;
294d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viveretteimport android.graphics.Color;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.DashPathEffect;
3287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.LinearGradient;
34b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craikimport android.graphics.Outline;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint;
36519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.Path;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat;
3843027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuff;
3943027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuffColorFilter;
40519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.RadialGradient;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.SweepGradient;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
46ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viveretteimport android.util.DisplayMetrics;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport com.android.internal.R;
5152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
565f63721a6c2c29e639d8d239834a825c535c034aAlan Viveretteimport java.lang.annotation.Retention;
575f63721a6c2c29e639d8d239834a825c535c034aAlan Viveretteimport java.lang.annotation.RetentionPolicy;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
6017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * A Drawable with a color gradient for buttons, backgrounds, etc.
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
62dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code>&lt;shape></code> element. For more
63dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a
64dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_visible
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_shape
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadius
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thickness
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_useLevel
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_width
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_height
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_startColor
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerColor
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_endColor
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_angle
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_type
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerX
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerY
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_gradientRadius
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSolid_color
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_width
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_color
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashWidth
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashGap
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_left
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_top
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_right
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_bottom
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GradientDrawable extends Drawable {
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a rectangle, possibly with rounded corners
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RECTANGLE = 0;
9917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is an ellipse
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    public static final int OVAL = 1;
10417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a line
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LINE = 2;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shape is a ring.
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RING = 3;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1155f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    /** @hide */
1165f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @IntDef({RECTANGLE, OVAL, LINE, RING})
1175f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Retention(RetentionPolicy.SOURCE)
1185f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public @interface Shape {}
1195f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is linear (default.)
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int LINEAR_GRADIENT = 0;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is circular.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int RADIAL_GRADIENT = 1;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gradient is a sweep.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int SWEEP_GRADIENT  = 2;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1355f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    /** @hide */
1365f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @IntDef({LINEAR_GRADIENT, RADIAL_GRADIENT, SWEEP_GRADIENT})
1375f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Retention(RetentionPolicy.SOURCE)
1385f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public @interface GradientType {}
1395f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette
140b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is in pixels. */
141b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_PIXELS = 0;
142b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
143b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is a fraction of the base size. */
144b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_FRACTION = 1;
145b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
146b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    /** Radius is a fraction of the bounds size. */
147b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette    private static final int RADIUS_TYPE_FRACTION_PARENT = 2;
148b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1495f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    /** @hide */
1505f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @IntDef({RADIUS_TYPE_PIXELS, RADIUS_TYPE_FRACTION, RADIUS_TYPE_FRACTION_PARENT})
1515f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Retention(RetentionPolicy.SOURCE)
1525f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public @interface RadiusType {}
1535f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette
15452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f;
15552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private static final float DEFAULT_THICKNESS_RATIO = 9.0f;
15652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private GradientState mGradientState;
15817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1596a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik    private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Rect mPadding;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mStrokePaint;   // optional, set by the caller
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ColorFilter mColorFilter;   // optional, set by the caller
16343027b7bca554818cc4223389747d661819d5706Alan Viverette    private PorterDuffColorFilter mTintFilter;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mAlpha = 0xFF;  // modified by the caller
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Path mPath = new Path();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final RectF mRect = new RectF();
168e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Paint mLayerPaint;    // internal, used if we use saveLayer()
17045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private boolean mGradientIsDirty;
171684385ddde2ac0c26de0862390ad713aff3fb149Romain Guy    private boolean mMutated;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Path mRingPath;
1731041aded2df45094c36831028245fb7c5e9b67b7Romain Guy    private boolean mPathIsDirty = true;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1753aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase    /** Current gradient radius, valid when {@link #mGradientIsDirty} is false. */
176861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    private float mGradientRadius;
177861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Controls how the gradient is oriented relative to the drawable's bounds
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public enum Orientation {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top to the bottom */
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TOP_BOTTOM,
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top-right to the bottom-left */
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TR_BL,
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the right to the left */
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RIGHT_LEFT,
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom-right to the top-left */
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BR_TL,
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom to the top */
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BOTTOM_TOP,
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the bottom-left to the top-right */
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        BL_TR,
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the left to the right */
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        LEFT_RIGHT,
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /** draw the gradient from the top-left to the bottom-right */
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TL_BR,
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GradientDrawable() {
20145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        this(new GradientState(Orientation.TOP_BOTTOM, null), null);
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new gradient drawable given an orientation and an array
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of colors for the gradient.
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20880756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public GradientDrawable(Orientation orientation, @ColorInt int[] colors) {
20945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        this(new GradientState(orientation, colors), null);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean getPadding(Rect padding) {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPadding != null) {
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            padding.set(mPadding);
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.getPadding(padding);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
22341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Specifies radii for each of the 4 corners. For each corner, the array
22441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * contains 2 values, <code>[X_radius, Y_radius]</code>. The corners are
22541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * ordered top-left, top-right, bottom-right, bottom-left. This property
22641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * is honored only when the shape is of type {@link #RECTANGLE}.
22741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
22841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
2298bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
23041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
2318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
23241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param radii an array of length >= 8 containing 4 pairs of X and Y
23341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *              radius for each corner, specified in pixels
2348bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2358bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
2368bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setShape(int)
23741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setCornerRadius(float)
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
23941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public void setCornerRadii(@Nullable float[] radii) {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setCornerRadii(radii);
2411041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
2429891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
24641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the radii for each of the 4 corners. For each corner, the array
24741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * contains 2 values, <code>[X_radius, Y_radius]</code>. The corners are
24841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * ordered top-left, top-right, bottom-right, bottom-left.
24941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
25041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * If the radius was previously set with {@link #setCornerRadius(float)},
25141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * or if the corners are not rounded, this method will return {@code null}.
25241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
25341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return an array containing the radii for each of the 4 corners, or
25441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *         {@code null}
25541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setCornerRadii(float[])
25641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
25741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    @Nullable
25841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float[] getCornerRadii() {
25941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mRadiusArray.clone();
26041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
26141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
26241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
26341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Specifies the radius for the corners of the gradient. If this is > 0,
26441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * then the drawable is drawn in a round-rectangle, rather than a
26541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * rectangle. This property is honored only when the shape is of type
26641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #RECTANGLE}.
26741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
26841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
2698bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
27041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
2718bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2728bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param radius The radius in pixels of the corners of the rectangle shape
2738bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
2748bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
2758bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setCornerRadii(float[])
27617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setShape(int)
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setCornerRadius(float radius) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setCornerRadius(radius);
2801041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
2819891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
28541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the radius for the corners of the gradient.
28641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
28741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * If the radius was previously set with {@link #setCornerRadii(float[])},
28841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * or if the corners are not rounded, this method will return {@code null}.
28941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
29041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the radius in pixels of the corners of the rectangle shape, or 0
29141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setCornerRadius
29241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
29341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float getCornerRadius() {
29441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mRadius;
29541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
29641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
29741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
2988bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Set the stroke width and color for the drawable. If width is zero,
2998bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * then no stroke is drawn.</p>
3008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
3038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width in pixels of the stroke
3058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param color The color of the stroke
3068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
30817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setStroke(int, int, float, float)
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
31080756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setStroke(int width, @ColorInt int color) {
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setStroke(width, color, 0, 0);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
315a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p>Set the stroke width and color state list for the drawable. If width
316a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * is zero, then no stroke is drawn.</p>
317a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p><strong>Note</strong>: changing this property will affect all instances
318a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * of a drawable loaded from a resource. It is recommended to invoke
319a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * {@link #mutate()} before changing this property.</p>
320a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
321a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param width The width in pixels of the stroke
322a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param colorStateList The color state list of the stroke
323a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
324a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #mutate()
325a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #setStroke(int, ColorStateList, float, float)
326a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     */
327a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public void setStroke(int width, ColorStateList colorStateList) {
328a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        setStroke(width, colorStateList, 0, 0);
329a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
330a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
331a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    /**
3328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Set the stroke width and color for the drawable. If width is zero,
3338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * then no stroke is drawn. This method can also be used to dash the stroke.</p>
3348bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
3358bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
3368bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
3378bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3388bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width in pixels of the stroke
3398bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param color The color of the stroke
34017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
3418bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param dashGap The gap in pixels between dashes
3428bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
3438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
34417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setStroke(int, int)
3458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
34680756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) {
34740df78153987409dbf299b84da9784b69029e184Alan Viverette        mGradientState.setStroke(width, ColorStateList.valueOf(color), dashWidth, dashGap);
348a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        setStrokeInternal(width, color, dashWidth, dashGap);
349a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
351a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    /**
352a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p>Set the stroke width and color state list for the drawable. If width
353a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * is zero, then no stroke is drawn. This method can also be used to dash
354a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * the stroke.</p>
355a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * <p><strong>Note</strong>: changing this property will affect all instances
356a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * of a drawable loaded from a resource. It is recommended to invoke
357a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * {@link #mutate()} before changing this property.</p>
358a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
359a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param width The width in pixels of the stroke
360a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param colorStateList The color state list of the stroke
361a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes
362a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @param dashGap The gap in pixels between dashes
363a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     *
364a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #mutate()
365a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     * @see #setStroke(int, ColorStateList)
366a211dd28b93473c452d68432c602d5209b01c178Alan Viverette     */
367a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    public void setStroke(
368a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            int width, ColorStateList colorStateList, float dashWidth, float dashGap) {
36940df78153987409dbf299b84da9784b69029e184Alan Viverette        mGradientState.setStroke(width, colorStateList, dashWidth, dashGap);
37040df78153987409dbf299b84da9784b69029e184Alan Viverette        final int color;
3717c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        if (colorStateList == null) {
37240df78153987409dbf299b84da9784b69029e184Alan Viverette            color = Color.TRANSPARENT;
3737c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        } else {
3747c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette            final int[] stateSet = getState();
37540df78153987409dbf299b84da9784b69029e184Alan Viverette            color = colorStateList.getColorForState(stateSet, 0);
3767c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        }
37740df78153987409dbf299b84da9784b69029e184Alan Viverette        setStrokeInternal(width, color, dashWidth, dashGap);
378a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    }
379a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
380a211dd28b93473c452d68432c602d5209b01c178Alan Viverette    private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) {
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStrokePaint == null)  {
3826a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStyle(Paint.Style.STROKE);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setStrokeWidth(width);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setColor(color);
38717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        DashPathEffect e = null;
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (dashWidth > 0) {
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0);
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStrokePaint.setPathEffect(e);
3939891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3958bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3968bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
3978bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
3988bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the size of the shape drawn by this drawable.</p>
3998bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
4008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
4018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
4028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param width The width of the shape used by this drawable
4048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param height The height of the shape used by this drawable
4058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
4078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setGradientType(int)
4088bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setSize(int width, int height) {
4101041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mGradientState.setSize(width, height);
4111041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
4129891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
4158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
4168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p>Sets the type of shape used to draw the gradient.</p>
4178bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * <p><strong>Note</strong>: changing this property will affect all instances
4188bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
4198bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * {@link #mutate()} before changing this property.</p>
4208bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4218bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param shape The desired shape for this drawable: {@link #LINE},
4228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *              {@link #OVAL}, {@link #RECTANGLE} or {@link #RING}
4238bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4248bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
4258bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4265f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setShape(@Shape int shape) {
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRingPath = null;
4281041aded2df45094c36831028245fb7c5e9b67b7Romain Guy        mPathIsDirty = true;
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setShape(shape);
4309891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
4345f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * Returns the type of shape used by this drawable, one of {@link #LINE},
4355f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * {@link #OVAL}, {@link #RECTANGLE} or {@link #RING}.
4365f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     *
4375f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * @return the type of shape used by this drawable
4385f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * @see #setShape(int)
4395f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     */
4405f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Shape
4415f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public int getShape() {
4425f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        return mGradientState.mShape;
4435f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    }
4445f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette
4455f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    /**
44641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the type of gradient used by this drawable.
44741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
44841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
4498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
45041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
4518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param gradient The type of the gradient: {@link #LINEAR_GRADIENT},
4538bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *                 {@link #RADIAL_GRADIENT} or {@link #SWEEP_GRADIENT}
4548bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4558bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
45641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientType()
4578bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4585f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setGradientType(@GradientType int gradient) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setGradientType(gradient);
4603aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4619891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4648bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
46541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the type of gradient used by this drawable, one of
46641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #LINEAR_GRADIENT}, {@link #RADIAL_GRADIENT}, or
46741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #SWEEP_GRADIENT}.
46841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
46941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the type of gradient used by this drawable
47041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientType(int)
47141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
4725f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @GradientType
47341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public int getGradientType() {
47441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mGradient;
47541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
47641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
47741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
47841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the center location in pixels of the gradient. The radius is
47941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * honored only when the gradient type is set to {@link #RADIAL_GRADIENT}
48041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * or {@link #SWEEP_GRADIENT}.
48141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
48241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
4838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
48441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
4858bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
48641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param x the x coordinate of the gradient's center in pixels
48741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param y the y coordinate of the gradient's center in pixels
4888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4898bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
4908bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setGradientType(int)
49141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientCenterX()
49241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientCenterY()
4938bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientCenter(float x, float y) {
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setGradientCenter(x, y);
4963aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4979891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
50141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the center X location of this gradient in pixels.
50241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
50341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the center X location of this gradient in pixels
50441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientCenter(float, float)
50541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
50641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float getGradientCenterX() {
50741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mCenterX;
50841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
50941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
51041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
51141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the center Y location of this gradient in pixels.
51241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
51341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the center Y location of this gradient in pixels
51441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientCenter(float, float)
51541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
51641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float getGradientCenterY() {
51741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mCenterY;
51841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
51941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
52041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
52141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the radius of the gradient. The radius is honored only when the
52241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * gradient type is set to {@link #RADIAL_GRADIENT}.
52341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
52441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
5258bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
52641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
5278bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
52841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param gradientRadius the radius of the gradient in pixels
5298bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
5308bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
53117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setGradientType(int)
53241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientRadius()
5338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientRadius(float gradientRadius) {
535861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        mGradientState.setGradientRadius(gradientRadius, TypedValue.COMPLEX_UNIT_PX);
5363aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
5379891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5408bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
541861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * Returns the radius of the gradient in pixels. The radius is valid only
542861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * when the gradient type is set to {@link #RADIAL_GRADIENT}.
543861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     *
54441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the radius of the gradient in pixels
54541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientRadius(float)
546861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     */
547861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    public float getGradientRadius() {
548861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        if (mGradientState.mGradient != RADIAL_GRADIENT) {
549861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette            return 0;
550861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        }
551861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
552861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        ensureValidRect();
553861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        return mGradientRadius;
554861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    }
555861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
556861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    /**
55741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets whether or not this drawable will honor its {@code level} property.
55841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
55941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
5608bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
56141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
5628bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
56341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param useLevel {@code true} if this drawable should honor its level,
56441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *                 {@code false} otherwise
5658bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
5668bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
5670b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette     * @see #setLevel(int)
5680b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette     * @see #getLevel()
5695f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * @see #getUseLevel()
5708bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setUseLevel(boolean useLevel) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.mUseLevel = useLevel;
5733aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
5749891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
57617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
57741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
57841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns whether or not this drawable will honor its {@code level}
57941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * property.
58041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
58141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return {@code true} if this drawable should honor its level,
58241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *         {@code false} otherwise
58341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setUseLevel(boolean)
58441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
5855f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public boolean getUseLevel() {
58641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mUseLevel;
58741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
58841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int modulateAlpha(int alpha) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int scale = mAlpha + (mAlpha >> 7);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return alpha * scale >> 8;
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5948bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
5958bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * Returns the orientation of the gradient defined in this drawable.
59641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
59741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the orientation of the gradient defined in this drawable
59841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setOrientation(Orientation)
5998bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
6008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public Orientation getOrientation() {
6018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        return mGradientState.mOrientation;
6028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
6048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
60541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the orientation of the gradient defined in this drawable.
60641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
60741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing orientation will affect all instances
6088bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
60941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing the orientation.
61017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
61141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param orientation the desired orientation (angle) of the gradient
61217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
61317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #mutate()
61441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getOrientation()
6158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
6168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public void setOrientation(Orientation orientation) {
6178bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        mGradientState.mOrientation = orientation;
6183aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
6198bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
6208bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6218bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
6228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
623e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Sets the colors used to draw the gradient.
624e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
625e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Each color is specified as an ARGB integer and the array must contain at
626e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * least 2 colors.
627e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
628e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <strong>Note</strong>: changing colors will affect all instances of a
629e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * drawable loaded from a resource. It is recommended to invoke
630e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * {@link #mutate()} before changing the colors.
6318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
632e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @param colors an array containing 2 or more ARGB colors
6338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
63417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColor(int)
6358bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
63680756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColors(@ColorInt int[] colors) {
637e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setGradientColors(colors);
6383aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
6398bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
6408bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6418bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
64241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
64341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the colors used to draw the gradient, or {@code null} if the
64441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * gradient is drawn using a single color or no colors.
64541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
64641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the colors used to draw the gradient, or {@code null}
64741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColors(int[] colors)
64841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
64941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    @Nullable
65041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public int[] getColors() {
6515f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        return mGradientState.mGradientColors == null ?
6525f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                null : mGradientState.mGradientColors.clone();
65341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
65441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
65616f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette    public void draw(Canvas canvas) {
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ensureValidRect()) {
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // nothing to draw
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // remember the alpha values, in case we temporarily overwrite them
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // when we modulate them with mAlpha
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevFillAlpha = mFillPaint.getAlpha();
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevStrokeAlpha = mStrokePaint != null ? mStrokePaint.getAlpha() : 0;
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the modulate alpha values
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currFillAlpha = modulateAlpha(prevFillAlpha);
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
670e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
671e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                mStrokePaint.getStrokeWidth() > 0;
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean haveFill = currFillAlpha > 0;
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final GradientState st = mGradientState;
67443027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter;
67543027b7bca554818cc4223389747d661819d5706Alan Viverette
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  we need a layer iff we're drawing both a fill and stroke, and the
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroke is non-opaque, and our shapetype actually supports
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fill+stroke. Otherwise we can just draw the stroke (if any) on top
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            of the fill (if any) without worrying about blending artifacts.
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
68143027b7bca554818cc4223389747d661819d5706Alan Viverette        final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
68243027b7bca554818cc4223389747d661819d5706Alan Viverette                 currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  Drawing with a layer is slower than direct drawing, but it
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            allows us to apply paint effects like alpha and colorfilter to
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            the result of multiple separate draws. In our case, if the user
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asks for a non-opaque alpha value (via setAlpha), and we're
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroking, then we need to apply the alpha AFTER we've drawn
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            both the fill and the stroke.
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        */
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLayerPaint == null) {
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLayerPaint = new Paint();
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
69507c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mLayerPaint.setDither(st.mDither);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayerPaint.setAlpha(mAlpha);
69743027b7bca554818cc4223389747d661819d5706Alan Viverette            mLayerPaint.setColorFilter(colorFilter);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float rad = mStrokePaint.getStrokeWidth();
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.saveLayer(mRect.left - rad, mRect.top - rad,
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             mRect.right + rad, mRect.bottom + rad,
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             mLayerPaint, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't perform the filter in our individual paints
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // since the layer will do it for us
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setColorFilter(null);
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setColorFilter(null);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*  if we're not using a layer, apply the dither/filter to our
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                individual paints
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(currFillAlpha);
71307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mFillPaint.setDither(st.mDither);
71443027b7bca554818cc4223389747d661819d5706Alan Viverette            mFillPaint.setColorFilter(colorFilter);
715e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (colorFilter != null && st.mSolidColors == null) {
716813680780f365648b39873fa26dfae0123d51aedChet Haase                mFillPaint.setColor(mAlpha << 24);
71741c769d9a8858ad20b0a6ed942a1cea19ba59d2dRomain Guy            }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(currStrokeAlpha);
72007c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette                mStrokePaint.setDither(st.mDither);
72143027b7bca554818cc4223389747d661819d5706Alan Viverette                mStrokePaint.setColorFilter(colorFilter);
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
724e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (st.mShape) {
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RECTANGLE:
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mRadiusArray != null) {
728e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(mPath, mFillPaint);
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawPath(mPath, mStrokePaint);
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
73361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else if (st.mRadius > 0.0f) {
7344e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // since the caller is only giving us 1 value, we will force
7354e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // it to be square if the rect is too small in one dimension
7364e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // to show it. If we did nothing, Skia would clamp the rad
73761c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    // independently along each axis, giving us a thin ellipse
7384e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // if the rect were very wide but not very tall
739b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    float rad = Math.min(st.mRadius,
740b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(mRect.width(), mRect.height()) * 0.5f);
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawRoundRect(mRect, rad, rad, mFillPaint);
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
74561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else {
74643027b7bca554818cc4223389747d661819d5706Alan Viverette                    if (mFillPaint.getColor() != 0 || colorFilter != null ||
747cf8675ee176a375f873792684d38a47f78348dffRomain Guy                            mFillPaint.getShader() != null) {
748cf8675ee176a375f873792684d38a47f78348dffRomain Guy                        canvas.drawRect(mRect, mFillPaint);
749cf8675ee176a375f873792684d38a47f78348dffRomain Guy                    }
75061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    if (haveStroke) {
75161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        canvas.drawRect(mRect, mStrokePaint);
75261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case OVAL:
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawOval(mRect, mFillPaint);
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawOval(mRect, mStrokePaint);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LINE: {
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                RectF r = mRect;
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float y = r.centerY();
76471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                if (haveStroke) {
76571b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                    canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
76671b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RING:
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Path path = buildRing(st);
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawPath(path, mFillPaint);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(path, mStrokePaint);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
77717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.restore();
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(prevFillAlpha);
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(prevStrokeAlpha);
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
787e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
788e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    private void buildPathIfDirty() {
789e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        final GradientState st = mGradientState;
7903aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mPathIsDirty) {
7913aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            ensureValidRect();
792e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.reset();
793e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
7943aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mPathIsDirty = false;
795e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        }
796e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    }
797e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Path buildRing(GradientState st) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = false;
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8020b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette        float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;
80317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF bounds = new RectF(mRect);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float x = bounds.width() / 2.0f;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float y = bounds.height() / 2.0f;
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float thickness = st.mThickness != -1 ?
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mThickness : bounds.width() / st.mThicknessRatio;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // inner radius
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius = st.mInnerRadius != -1 ?
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mInnerRadius : bounds.width() / st.mInnerRadiusRatio;
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF innerBounds = new RectF(bounds);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        innerBounds.inset(x - radius, y - radius);
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds = new RectF(innerBounds);
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds.inset(-thickness, -thickness);
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath == null) {
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRingPath = new Path();
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
824b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            mRingPath.reset();
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Path ringPath = mRingPath;
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // arcTo treats the sweep angle mod 360, so check for that, since we
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // think 360 means draw the entire oval
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sweep < 360 && sweep > -360) {
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.setFillType(Path.FillType.EVEN_ODD);
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner top
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.moveTo(x + radius, y);
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer top
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.lineTo(x + radius + thickness, y);
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer arc
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(bounds, 0.0f, sweep, false);
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner arc
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(innerBounds, sweep, -sweep, false);
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.close();
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // add the entire ovals
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(bounds, Path.Direction.CW);
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(innerBounds, Path.Direction.CCW);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ringPath;
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
85141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Changes this drawable to use a single color instead of a gradient.
85241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
85341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing color will affect all instances of a
85441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * drawable loaded from a resource. It is recommended to invoke
85541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing the color.
8568bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
8578bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param argb The color used to fill the shape
8588bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
8598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
86017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColors(int[])
86141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getColor
8628bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
86380756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColor(@ColorInt int argb) {
864e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(ColorStateList.valueOf(argb));
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFillPaint.setColor(argb);
8669891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    /**
870519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * Changes this drawable to use a single color state list instead of a
8717c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * gradient. Calling this method with a null argument will clear the color
8727c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * and is equivalent to calling {@link #setColor(int)} with the argument
8737c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * {@link Color#TRANSPARENT}.
874519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <p>
875519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <strong>Note</strong>: changing color will affect all instances of a
876519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * drawable loaded from a resource. It is recommended to invoke
877519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * {@link #mutate()} before changing the color.</p>
878519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     *
879519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @param colorStateList The color state list used to fill the shape
88041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
881519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @see #mutate()
88241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getColor
883519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     */
8845f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setColor(@Nullable ColorStateList colorStateList) {
885e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(colorStateList);
88640df78153987409dbf299b84da9784b69029e184Alan Viverette        final int color;
8877c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        if (colorStateList == null) {
88840df78153987409dbf299b84da9784b69029e184Alan Viverette            color = Color.TRANSPARENT;
8897c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        } else {
89040df78153987409dbf299b84da9784b69029e184Alan Viverette            final int[] stateSet = getState();
89140df78153987409dbf299b84da9784b69029e184Alan Viverette            color = colorStateList.getColorForState(stateSet, 0);
8927c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        }
89340df78153987409dbf299b84da9784b69029e184Alan Viverette        mFillPaint.setColor(color);
89440df78153987409dbf299b84da9784b69029e184Alan Viverette        invalidateSelf();
895519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
896519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
89741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
89841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the color state list used to fill the shape, or {@code null} if
89941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * the shape is filled with a gradient or has no fill color.
90041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
90141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the color state list used to fill this gradient, or {@code null}
90241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
90341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColor(int)
90441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColor(ColorStateList)
90541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
9065f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Nullable
90741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public ColorStateList getColor() {
90841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mSolidColors;
90941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
91041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
911519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
91212b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette    protected boolean onStateChange(int[] stateSet) {
913a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        boolean invalidateSelf = false;
914a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
915a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
916e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        final ColorStateList solidColors = s.mSolidColors;
917e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (solidColors != null) {
918e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int newColor = solidColors.getColorForState(stateSet, 0);
919519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int oldColor = mFillPaint.getColor();
920519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            if (oldColor != newColor) {
921519494e207322581075c8ea884fde9d33bb9209eAlan Viverette                mFillPaint.setColor(newColor);
922616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                invalidateSelf = true;
923a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            }
924a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
925a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
926616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        final Paint strokePaint = mStrokePaint;
927616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        if (strokePaint != null) {
928e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final ColorStateList strokeColors = s.mStrokeColors;
929e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (strokeColors != null) {
930e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int newColor = strokeColors.getColorForState(stateSet, 0);
931e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int oldColor = strokePaint.getColor();
932e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (oldColor != newColor) {
933e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    strokePaint.setColor(newColor);
934616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                    invalidateSelf = true;
935616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                }
936519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            }
937519494e207322581075c8ea884fde9d33bb9209eAlan Viverette        }
938519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
93943027b7bca554818cc4223389747d661819d5706Alan Viverette        if (s.mTint != null && s.mTintMode != null) {
94043027b7bca554818cc4223389747d661819d5706Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode);
94143027b7bca554818cc4223389747d661819d5706Alan Viverette            invalidateSelf = true;
94243027b7bca554818cc4223389747d661819d5706Alan Viverette        }
94343027b7bca554818cc4223389747d661819d5706Alan Viverette
944a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        if (invalidateSelf) {
945a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            invalidateSelf();
946a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            return true;
947a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
948a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
949a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return false;
950519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
951519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
952519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
953519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    public boolean isStateful() {
954a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
955a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return super.isStateful()
956e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mSolidColors != null && s.mSolidColors.isStateful())
957e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mStrokeColors != null && s.mStrokeColors.isStateful())
95843027b7bca554818cc4223389747d661819d5706Alan Viverette                || (s.mTint != null && s.mTint.isStateful());
959519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
960519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
962ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    public @Config int getChangingConfigurations() {
963e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9658bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
9689891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (alpha != mAlpha) {
9699891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mAlpha = alpha;
9709891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
9719891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
975b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
976b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mAlpha;
977b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
978b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
979b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
98107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        if (dither != mGradientState.mDither) {
98207c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mGradientState.mDither = dither;
9839891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
9849891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
9885f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Nullable
98938b5f597de96cd892add9017dc810212f549bf68John Spurlock    public ColorFilter getColorFilter() {
99038b5f597de96cd892add9017dc810212f549bf68John Spurlock        return mColorFilter;
99138b5f597de96cd892add9017dc810212f549bf68John Spurlock    }
99238b5f597de96cd892add9017dc810212f549bf68John Spurlock
99338b5f597de96cd892add9017dc810212f549bf68John Spurlock    @Override
9945f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setColorFilter(@Nullable ColorFilter colorFilter) {
995bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        if (colorFilter != mColorFilter) {
996bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mColorFilter = colorFilter;
9979891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
9989891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10025f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setTintList(@Nullable ColorStateList tint) {
100343027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTint = tint;
100443027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
100543027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
100643027b7bca554818cc4223389747d661819d5706Alan Viverette    }
100743027b7bca554818cc4223389747d661819d5706Alan Viverette
100843027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
10095f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
101043027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTintMode = tintMode;
101143027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
101243027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
101343027b7bca554818cc4223389747d661819d5706Alan Viverette    }
101443027b7bca554818cc4223389747d661819d5706Alan Viverette
101543027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
1017888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ?
10180a1c6f021be032f5aecb341c2794efb06c0a8a0dAlan Viverette                PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect r) {
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onBoundsChange(r);
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRingPath = null;
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
10263aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10300b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onLevelChange(level);
10323aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10393aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase     * This checks mGradientIsDirty, and if it is true, recomputes both our drawing
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle (mRect) and the gradient itself, since it depends on our
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle too.
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the resulting rectangle is not empty, false otherwise
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean ensureValidRect() {
10453aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mGradientIsDirty) {
10463aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mGradientIsDirty = false;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect bounds = getBounds();
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float inset = 0;
105017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mStrokePaint != null) {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inset = mStrokePaint.getStrokeWidth() * 0.5f;
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final GradientState st = mGradientState;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRect.set(bounds.left + inset, bounds.top + inset,
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                      bounds.right - inset, bounds.bottom - inset);
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1060e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int[] gradientColors = st.mGradientColors;
1061e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (gradientColors != null) {
1062e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final RectF r = mRect;
1063e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final float x0, x1, y0, y1;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mGradient == LINEAR_GRADIENT) {
10660b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (st.mOrientation) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TOP_BOTTOM:
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.bottom;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TR_BL:
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.bottom;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case RIGHT_LEFT:
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = y0;
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BR_TL:
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.bottom;
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.top;
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BOTTOM_TOP:
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.top;
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BL_TR:
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.top;
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case LEFT_RIGHT:
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = y0;
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    default:/* TL_BR */
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.bottom;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
1103e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            gradientColors, st.mPositions, Shader.TileMode.CLAMP));
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == RADIAL_GRADIENT) {
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1108861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    float radius = st.mGradientRadius;
1109b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
1110b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // Fall back to parent width or height if intrinsic
1111b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // size is not specified.
1112b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float width = st.mWidth >= 0 ? st.mWidth : r.width();
1113b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float height = st.mHeight >= 0 ? st.mHeight : r.height();
1114b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        radius *= Math.min(width, height);
1115b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    } else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) {
1116861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                        radius *= Math.min(r.width(), r.height());
1117861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
1118b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1119861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    if (st.mUseLevel) {
11200b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                        radius *= getLevel() / 10000.0f;
1121861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
1122b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1123861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mGradientRadius = radius;
1124b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1125b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                    if (radius <= 0) {
1126b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // We can't have a shader with non-positive radius, so
1127b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // let's have a very, very small radius.
1128b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                        radius = 0.001f;
1129b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    }
1130b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1131861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mFillPaint.setShader(new RadialGradient(
1132e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP));
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == SWEEP_GRADIENT) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1137e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    int[] tempColors = gradientColors;
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    float[] tempPositions = null;
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (st.mUseLevel) {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempColors = st.mTempColors;
1142e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        final int length = gradientColors.length;
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempColors == null || tempColors.length != length + 1) {
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempColors = st.mTempColors = new int[length + 1];
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1146e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        System.arraycopy(gradientColors, 0, tempColors, 0, length);
1147e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        tempColors[length] = gradientColors[length - 1];
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions = st.mTempPositions;
115052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        final float fraction = 1.0f / (length - 1);
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempPositions == null || tempPositions.length != length + 1) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions = st.mTempPositions = new float[length + 1];
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11550b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                        final float level = getLevel() / 10000.0f;
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (int i = 0; i < length; i++) {
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions[i] = i * fraction * level;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions[length] = 1.0f;
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
11634d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                }
11644d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette
11654d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // If we don't have a solid color, the alpha channel must be
11664d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // maxed out so that alpha modulation works correctly.
1167e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (st.mSolidColors == null) {
11684d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                    mFillPaint.setColor(Color.BLACK);
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return !mRect.isEmpty();
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1176ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
1177ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            @NonNull AttributeSet attrs, @Nullable Theme theme)
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
1179ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        super.inflate(r, parser, attrs, theme);
1180ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1181ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        mGradientState.setDensity(Drawable.resolveDensity(r, 0));
1182ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
118352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawable);
118417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        updateStateFromTypedArray(a);
118552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        a.recycle();
118652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
118752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        inflateChildElements(r, parser, attrs, theme);
118852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
118945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(r);
119052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
119152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
119252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
1193ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    public void applyTheme(@NonNull Theme t) {
119452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        super.applyTheme(t);
119552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
119652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
119717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state == null) {
119817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            return;
119952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
120052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1201ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        state.setDensity(Drawable.resolveDensity(t.getResources(), 0));
1202ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
120317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state.mThemeAttrs != null) {
120417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            final TypedArray a = t.resolveAttributes(
120517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    state.mThemeAttrs, R.styleable.GradientDrawable);
120617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            updateStateFromTypedArray(a);
120717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            a.recycle();
120817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
120952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
121045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mTint != null && state.mTint.canApplyTheme()) {
1211e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mTint = state.mTint.obtainForTheme(t);
121245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
121345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1214e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) {
1215e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mSolidColors = state.mSolidColors.obtainForTheme(t);
121645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
121745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1218e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) {
1219e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mStrokeColors = state.mStrokeColors.obtainForTheme(t);
122045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
122145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
122217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        applyThemeChildElements(t);
122352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
122445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(t.getResources());
122552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
122652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
122752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
122852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Updates the constant state from the values in the typed array.
122952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
123052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void updateStateFromTypedArray(TypedArray a) {
123152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
123252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
12338e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
12348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
12358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
123617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
123717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
123852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
123917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape);
124007c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither);
124152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
124252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (state.mShape == RING) {
124317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mInnerRadius = a.getDimensionPixelSize(
124417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_innerRadius, state.mInnerRadius);
124552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
124617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mInnerRadius == -1) {
124752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mInnerRadiusRatio = a.getFloat(
124817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_innerRadiusRatio, state.mInnerRadiusRatio);
124952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
125052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
125117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mThickness = a.getDimensionPixelSize(
125217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_thickness, state.mThickness);
125352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
125417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mThickness == -1) {
125552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mThicknessRatio = a.getFloat(
125617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_thicknessRatio, state.mThicknessRatio);
125752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
125852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
125917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mUseLevelForShape = a.getBoolean(
126017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape);
126152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
126243027b7bca554818cc4223389747d661819d5706Alan Viverette
126343027b7bca554818cc4223389747d661819d5706Alan Viverette        final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1);
126443027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tintMode != -1) {
126543027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN);
126643027b7bca554818cc4223389747d661819d5706Alan Viverette        }
126743027b7bca554818cc4223389747d661819d5706Alan Viverette
126843027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint);
126943027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tint != null) {
127043027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTint = tint;
127143027b7bca554818cc4223389747d661819d5706Alan Viverette        }
127287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
127387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetLeft = a.getDimensionPixelSize(
127487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetLeft, state.mOpticalInsets.left);
127587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetTop = a.getDimensionPixelSize(
127687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetTop, state.mOpticalInsets.top);
127787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetRight = a.getDimensionPixelSize(
127887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetRight, state.mOpticalInsets.right);
127987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetBottom = a.getDimensionPixelSize(
128087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetBottom, state.mOpticalInsets.bottom);
128187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        state.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom);
128252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
128352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
128452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
128552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
1286d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
128752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
128852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
128952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void applyThemeChildElements(Theme t) {
129017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
129152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
129217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSize != null) {
129317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
129417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSize, R.styleable.GradientDrawableSize);
129517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSize(a);
129652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
129752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
129852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
129917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrGradient != null) {
130017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
130117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrGradient, R.styleable.GradientDrawableGradient);
130217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            try {
130317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(t.getResources(), a);
130417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } catch (XmlPullParserException e) {
1305c078c605ab904b0e4a5d793cbeffd78c340f2816Alan Viverette                rethrowAsRuntimeException(e);
130617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } finally {
130717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.recycle();
130817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            }
130952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
131052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
131117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSolid != null) {
131217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
131317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSolid, R.styleable.GradientDrawableSolid);
131417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSolid(a);
131552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
131652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
131752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
131817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrStroke != null) {
131917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
132017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrStroke, R.styleable.GradientDrawableStroke);
132117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableStroke(a);
132252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
132352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
132452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
132517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrCorners != null) {
132617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
132717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrCorners, R.styleable.DrawableCorners);
132817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateDrawableCorners(a);
132952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
133052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
133152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
133217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrPadding != null) {
133317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
133417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrPadding, R.styleable.GradientDrawablePadding);
133517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawablePadding(a);
133652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
133752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
133852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
133952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
134052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
134152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            Theme theme) throws XmlPullParserException, IOException {
134252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        TypedArray a;
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1345ed7894352f8addfe3d0da75cc7fe8bc6fef201dcRomain Guy        final int innerDepth = parser.getDepth() + 1;
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               && ((depth=parser.getDepth()) >= innerDepth
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       || type != XmlPullParser.END_TAG)) {
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth) {
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
135752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = parser.getName();
135917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (name.equals("size")) {
136117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSize);
136217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSize(a);
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("gradient")) {
136517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableGradient);
136617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(r, a);
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("solid")) {
136917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSolid);
137017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSolid(a);
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("stroke")) {
137317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableStroke);
137417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableStroke(a);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("corners")) {
137717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.DrawableCorners);
137817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateDrawableCorners(a);
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("padding")) {
138117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawablePadding);
138217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawablePadding(a);
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w("drawable", "Bad element under <shape>: " + name);
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
138752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
138852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
138952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
139017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawablePadding(TypedArray a) {
139117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
139252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
13938e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
13948e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
13958e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
139652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
139717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrPadding = a.extractThemeAttrs();
139817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1399982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        if (st.mPadding == null) {
1400982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette            st.mPadding = new Rect();
1401982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        }
1402982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette
140317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final Rect pad = st.mPadding;
140417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        pad.set(a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_left, pad.left),
140517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_top, pad.top),
140617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_right, pad.right),
140717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_bottom, pad.bottom));
140817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        mPadding = pad;
140952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
1410e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
141117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateDrawableCorners(TypedArray a) {
141217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
141317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14148e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
141717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
141817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrCorners = a.extractThemeAttrs();
141917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
142017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int radius = a.getDimensionPixelSize(
142117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.DrawableCorners_radius, (int) st.mRadius);
142252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        setCornerRadius(radius);
142317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
142417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
142517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topLeftRadius = a.getDimensionPixelSize(
142652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topLeftRadius, radius);
142717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topRightRadius = a.getDimensionPixelSize(
142852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topRightRadius, radius);
142917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomLeftRadius = a.getDimensionPixelSize(
143052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomLeftRadius, radius);
143117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomRightRadius = a.getDimensionPixelSize(
143252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomRightRadius, radius);
143352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (topLeftRadius != radius || topRightRadius != radius ||
143452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                bottomLeftRadius != radius || bottomRightRadius != radius) {
143552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // The corner radii are specified in clockwise order (see Path.addRoundRect())
143652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setCornerRadii(new float[] {
143752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topLeftRadius, topLeftRadius,
143852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topRightRadius, topRightRadius,
143952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomRightRadius, bottomRightRadius,
144052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomLeftRadius, bottomLeftRadius
144152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            });
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
144352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
144452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
144517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableStroke(TypedArray a) {
144617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
144717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14508e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
14518e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
145217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrStroke = a.extractThemeAttrs();
145317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14543b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // We have an explicit stroke defined, so the default stroke width
14553b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // must be at least 0 or the current stroke width.
14563b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        final int defaultStrokeWidth = Math.max(0, st.mStrokeWidth);
145752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int width = a.getDimensionPixelSize(
14583b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                R.styleable.GradientDrawableStroke_width, defaultStrokeWidth);
145952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final float dashWidth = a.getDimension(
146017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_dashWidth, st.mStrokeDashWidth);
146117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
146217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        ColorStateList colorStateList = a.getColorStateList(
146317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_color);
146417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList == null) {
1465e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            colorStateList = st.mStrokeColors;
146617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
146717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
146852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (dashWidth != 0.0f) {
146952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final float dashGap = a.getDimension(
147017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawableStroke_dashGap, st.mStrokeDashGap);
147152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList, dashWidth, dashGap);
147252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
147352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList);
147452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
147552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
147652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
147717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSolid(TypedArray a) {
14788e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final GradientState st = mGradientState;
14798e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
14808e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14818e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
14838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
14848e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mAttrSolid = a.extractThemeAttrs();
148517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
148652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final ColorStateList colorStateList = a.getColorStateList(
148752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableSolid_color);
148817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList != null) {
148917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            setColor(colorStateList);
149017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
149152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
149252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
149317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableGradient(Resources r, TypedArray a)
149452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            throws XmlPullParserException {
149552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState st = mGradientState;
149617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14978e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14988e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14998e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
150017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
150117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrGradient = a.extractThemeAttrs();
150217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
150317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterX = getFloatOrFraction(
150417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerX, st.mCenterX);
150517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterY = getFloatOrFraction(
150617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerY, st.mCenterY);
150717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mUseLevel = a.getBoolean(
150817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_useLevel, st.mUseLevel);
150917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mGradient = a.getInt(
151017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_type, st.mGradient);
151117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
151217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
151352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int startColor = a.getColor(
151452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_startColor, 0);
151552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final boolean hasCenterColor = a.hasValue(
151652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor);
151752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int centerColor = a.getColor(
151852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor, 0);
151952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int endColor = a.getColor(
152052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_endColor, 0);
152152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
152252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (hasCenterColor) {
1523e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[3];
1524e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1525e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = centerColor;
1526e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[2] = endColor;
152717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
152852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions = new float[3];
152952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[0] = 0.0f;
153052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // Since 0.5f is default value, try to take the one that isn't 0.5f
153152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY;
153252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[2] = 1f;
153352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
1534e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[2];
1535e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1536e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = endColor;
153752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
153852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
153952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (st.mGradient == LINEAR_GRADIENT) {
154017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
154152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            angle %= 360;
154252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
154352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (angle % 45 != 0) {
154452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(a.getPositionDescription()
154552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'angle' attribute to "
154652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "be a multiple of 45");
154752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
154852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
154917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            st.mAngle = angle;
155017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
155152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            switch (angle) {
155252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 0:
155352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.LEFT_RIGHT;
155452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
155552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 45:
155652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BL_TR;
155752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
155852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 90:
155952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BOTTOM_TOP;
156052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
156152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 135:
156252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BR_TL;
156352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
156452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 180:
156552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.RIGHT_LEFT;
156652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
156752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 225:
156852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TR_BL;
156952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
157052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 270:
157152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TOP_BOTTOM;
157252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
157352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 315:
157452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TL_BR;
157552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
157652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
157752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
157817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
157952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (tv != null) {
158052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                final float radius;
15815f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                final @RadiusType int radiusType;
158252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (tv.type == TypedValue.TYPE_FRACTION) {
158352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getFraction(1.0f, 1.0f);
158452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
158552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT)
158652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                            & TypedValue.COMPLEX_UNIT_MASK;
158752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) {
158852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION_PARENT;
158952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    } else {
159052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION;
159152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
15922efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else if (tv.type == TypedValue.TYPE_DIMENSION) {
159352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getDimension(r.getDisplayMetrics());
159452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
15952efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else {
15962efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radius = tv.getFloat();
15972efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
159852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
159952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
160052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadius = radius;
160152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadiusType = radiusType;
160252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            } else if (st.mGradient == RADIAL_GRADIENT) {
160352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(
160452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        a.getPositionDescription()
160552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'gradientRadius' "
160652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "attribute with radial type");
160752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
160852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
160952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
161052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
161117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSize(TypedArray a) {
161217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
161352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
16148e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
16158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
16168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
161752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
161817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrSize = a.extractThemeAttrs();
161917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
162017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mWidth = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_width, st.mWidth);
162117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mHeight = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_height, st.mHeight);
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedValue tv = a.peekValue(index);
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float v = defaultValue;
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tv != null) {
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean vIsFraction = tv.type == TypedValue.TYPE_FRACTION;
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v = vIsFraction ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return v;
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
163317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mWidth;
16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mHeight;
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
164317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
164487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    /** @hide */
164587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    @Override
164687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    public Insets getOpticalInsets() {
164787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        return mGradientState.mOpticalInsets;
164887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    }
164987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
16526efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mGradientState.mChangingConfigurations = getChangingConfigurations();
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState;
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1656888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    private boolean isOpaqueForState() {
1657888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        if (mGradientState.mStrokeWidth >= 0 && mStrokePaint != null
1658888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette                && !isOpaque(mStrokePaint.getColor())) {
1659888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1660888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1661888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
16625f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        // Don't check opacity if we're using a gradient, as we've already
16635f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        // checked the gradient opacity in mOpaqueOverShape.
16645f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        if (mGradientState.mGradientColors == null && !isOpaque(mFillPaint.getColor())) {
1665888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1666888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1667888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
1668888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return true;
1669888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
1670888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
167231ba192dd201df2cad96a8c503f730130ab0d80fChris Craik    public void getOutline(Outline outline) {
1673b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final GradientState st = mGradientState;
1674b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final Rect bounds = getBounds();
1675f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        // only report non-zero alpha if shape being drawn has consistent opacity over shape. Must
1676f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        // either not have a stroke, or have same stroke/fill opacity
1677f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        boolean useFillOpacity = st.mOpaqueOverShape && (mGradientState.mStrokeWidth <= 0
1678f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                || mStrokePaint == null
1679f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                || mStrokePaint.getAlpha() == mFillPaint.getAlpha());
1680f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        outline.setAlpha(useFillOpacity
1681f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                ? modulateAlpha(mFillPaint.getAlpha()) / 255.0f
1682f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                : 0.0f);
1683b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1684b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        switch (st.mShape) {
1685b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            case RECTANGLE:
1686b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadiusArray != null) {
1687e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
1688e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    outline.setConvexPath(mPath);
168931ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                    return;
1690b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
1691e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
1692b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                float rad = 0;
1693b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadius > 0.0f) {
1694b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    // clamp the radius based on width & height, matching behavior in draw()
1695b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    rad = Math.min(st.mRadius,
1696b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(bounds.width(), bounds.height()) * 0.5f);
1697b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
16987979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setRoundRect(bounds, rad);
169931ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
17007979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case OVAL:
17017979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setOval(bounds);
170231ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
17037979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case LINE:
17043b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // Hairlines (0-width stroke) must have a non-empty outline for
17053b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // shadows to draw correctly, so we'll use a very small width.
17063b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float halfStrokeWidth = mStrokePaint == null ?
17073b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                        0.0001f : mStrokePaint.getStrokeWidth() * 0.5f;
17083b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float centerY = bounds.centerY();
17093b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int top = (int) Math.floor(centerY - halfStrokeWidth);
17103b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
1711b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1712e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                outline.setRect(bounds.left, top, bounds.right, bottom);
171331ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
1714b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            default:
171531ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                // TODO: support more complex shapes
1716b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        }
1717b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
1718b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1719b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    @Override
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
1722ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientState = new GradientState(mGradientState, null);
172345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            updateLocalState(null);
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1729727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
1730727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
1731727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
1732727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
1733727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
1734727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
1735727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
1736727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final static class GradientState extends ConstantState {
1738ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int mChangingConfigurations;
17395f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @Shape int mShape = RECTANGLE;
17405f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @GradientType int mGradient = LINEAR_GRADIENT;
174171b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mAngle = 0;
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Orientation mOrientation;
1743e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mSolidColors;
1744e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mStrokeColors;
17455f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @ColorInt int[] mGradientColors;
17465f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @ColorInt int[] mTempColors; // no need to copy
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mTempPositions; // no need to copy
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mPositions;
174971b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mStrokeWidth = -1; // if >= 0 use stroking.
175071b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashWidth = 0.0f;
175171b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashGap = 0.0f;
175271b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mRadius = 0.0f; // use this if mRadiusArray is null
175371b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float[] mRadiusArray = null;
175471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public Rect mPadding = null;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mWidth = -1;
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mHeight = -1;
175717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
175817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
175917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mInnerRadius = -1;
176017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mThickness = -1;
176107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        public boolean mDither = false;
176287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        public Insets mOpticalInsets = Insets.NONE;
176307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette
1764969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterX = 0.5f;
1765969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterY = 0.5f;
1766969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mGradientRadius = 0.5f;
17675f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        @RadiusType int mGradientRadiusType = RADIUS_TYPE_PIXELS;
1768969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevel = false;
1769969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevelForShape = true;
1770969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette
1771969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverBounds;
1772969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverShape;
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
177443027b7bca554818cc4223389747d661819d5706Alan Viverette        ColorStateList mTint = null;
177543027b7bca554818cc4223389747d661819d5706Alan Viverette        PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
177643027b7bca554818cc4223389747d661819d5706Alan Viverette
1777ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        int mDensity = DisplayMetrics.DENSITY_DEFAULT;
1778ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
177952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mThemeAttrs;
178052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSize;
178152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrGradient;
178252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSolid;
178352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrStroke;
178452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrCorners;
178552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrPadding;
178652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1787e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public GradientState(Orientation orientation, int[] gradientColors) {
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOrientation = orientation;
1789e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            setGradientColors(gradientColors);
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1792ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public GradientState(@NonNull GradientState orig, @Nullable Resources res) {
1793ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mChangingConfigurations = orig.mChangingConfigurations;
1794ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mShape = orig.mShape;
1795ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradient = orig.mGradient;
1796ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAngle = orig.mAngle;
1797ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOrientation = orig.mOrientation;
1798ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mSolidColors = orig.mSolidColors;
1799ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mGradientColors != null) {
1800ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mGradientColors = orig.mGradientColors.clone();
1801562bf17c6c7c5226b2220e27a1543d4a43543d6cPhil Dubach            }
1802ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mPositions != null) {
1803ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPositions = orig.mPositions.clone();
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1805ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeColors = orig.mStrokeColors;
1806ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeWidth = orig.mStrokeWidth;
1807ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeDashWidth = orig.mStrokeDashWidth;
1808ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeDashGap = orig.mStrokeDashGap;
1809ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mRadius = orig.mRadius;
1810ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mRadiusArray != null) {
1811ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray = orig.mRadiusArray.clone();
18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1813ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mPadding != null) {
1814ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding = new Rect(orig.mPadding);
1815ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1816ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mWidth = orig.mWidth;
1817ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mHeight = orig.mHeight;
1818ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mInnerRadiusRatio = orig.mInnerRadiusRatio;
1819ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThicknessRatio = orig.mThicknessRatio;
1820ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mInnerRadius = orig.mInnerRadius;
1821ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThickness = orig.mThickness;
1822ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDither = orig.mDither;
1823ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpticalInsets = orig.mOpticalInsets;
1824ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mCenterX = orig.mCenterX;
1825ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mCenterY = orig.mCenterY;
1826ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientRadius = orig.mGradientRadius;
1827ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientRadiusType = orig.mGradientRadiusType;
1828ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mUseLevel = orig.mUseLevel;
1829ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mUseLevelForShape = orig.mUseLevelForShape;
1830ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpaqueOverBounds = orig.mOpaqueOverBounds;
1831ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpaqueOverShape = orig.mOpaqueOverShape;
1832ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mTint = orig.mTint;
1833ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mTintMode = orig.mTintMode;
1834ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThemeAttrs = orig.mThemeAttrs;
1835ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrSize = orig.mAttrSize;
1836ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrGradient = orig.mAttrGradient;
1837ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrSolid = orig.mAttrSolid;
1838ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrStroke = orig.mAttrStroke;
1839ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrCorners = orig.mAttrCorners;
1840ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrPadding = orig.mAttrPadding;
1841ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1842ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDensity = Drawable.resolveDensity(res, orig.mDensity);
1843ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mDensity != mDensity) {
1844ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                applyDensityScaling(orig.mDensity, mDensity);
1845ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1846ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        }
1847ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1848ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        /**
1849ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * Sets the constant state density.
1850ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * <p>
1851ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * If the density has been previously set, dispatches the change to
1852ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * subclasses so that density-dependent properties may be scaled as
1853ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * necessary.
1854ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         *
1855ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * @param targetDensity the new constant state density
1856ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         */
1857ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public final void setDensity(int targetDensity) {
1858ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mDensity != targetDensity) {
1859ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int sourceDensity = mDensity;
1860ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mDensity = targetDensity;
1861ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1862ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                applyDensityScaling(sourceDensity, targetDensity);
1863ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1864ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        }
1865ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1866ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        private void applyDensityScaling(int sourceDensity, int targetDensity) {
1867ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mInnerRadius > 0) {
1868ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mInnerRadius = Drawable.scaleFromDensity(
1869ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mInnerRadius, sourceDensity, targetDensity, true);
1870ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1871ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mThickness > 0) {
1872ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mThickness = Drawable.scaleFromDensity(
1873ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mThickness, sourceDensity, targetDensity, true);
1874ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1875ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mOpticalInsets != Insets.NONE) {
1876ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int left = Drawable.scaleFromDensity(
1877ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.left, sourceDensity, targetDensity, true);
1878ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int top = Drawable.scaleFromDensity(
1879ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.top, sourceDensity, targetDensity, true);
1880ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int right = Drawable.scaleFromDensity(
1881ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.right, sourceDensity, targetDensity, true);
1882ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int bottom = Drawable.scaleFromDensity(
1883ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.bottom, sourceDensity, targetDensity, true);
1884ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mOpticalInsets = Insets.of(left, top, right, bottom);
1885ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1886ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mPadding != null) {
1887ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.left = Drawable.scaleFromDensity(
1888ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.left, sourceDensity, targetDensity, false);
1889ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.top = Drawable.scaleFromDensity(
1890ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.top, sourceDensity, targetDensity, false);
1891ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.right = Drawable.scaleFromDensity(
1892ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.right, sourceDensity, targetDensity, false);
1893ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.bottom = Drawable.scaleFromDensity(
1894ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.bottom, sourceDensity, targetDensity, false);
1895ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1896ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mRadius > 0) {
1897ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadius = Drawable.scaleFromDensity(mRadius, sourceDensity, targetDensity);
1898ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1899ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mRadiusArray != null) {
1900ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[0] = Drawable.scaleFromDensity(
1901ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[0], sourceDensity, targetDensity, true);
1902ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[1] = Drawable.scaleFromDensity(
1903ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[1], sourceDensity, targetDensity, true);
1904ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[2] = Drawable.scaleFromDensity(
1905ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[2], sourceDensity, targetDensity, true);
1906ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[3] = Drawable.scaleFromDensity(
1907ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[3], sourceDensity, targetDensity, true);
1908ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1909ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeWidth > 0) {
1910ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeWidth = Drawable.scaleFromDensity(
1911ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeWidth, sourceDensity, targetDensity, true);
1912ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1913ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeDashWidth > 0) {
1914ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeDashWidth = Drawable.scaleFromDensity(
1915ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeDashGap, sourceDensity, targetDensity);
1916ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1917ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeDashGap > 0) {
1918ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeDashGap = Drawable.scaleFromDensity(
1919ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeDashGap, sourceDensity, targetDensity);
1920ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1921ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mGradientRadiusType == RADIUS_TYPE_PIXELS) {
1922ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mGradientRadius = Drawable.scaleFromDensity(
1923ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mGradientRadius, sourceDensity, targetDensity);
1924ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1925ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mWidth > 0) {
1926ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mWidth = Drawable.scaleFromDensity(mWidth, sourceDensity, targetDensity, true);
1927ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1928ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mHeight > 0) {
1929ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mHeight = Drawable.scaleFromDensity(mHeight, sourceDensity, targetDensity, true);
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
193152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
193252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
193352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
193452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
193545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mThemeAttrs != null
193645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSize != null || mAttrGradient != null
193745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSolid != null || mAttrStroke != null
193845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrCorners != null || mAttrPadding != null
193945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mTint != null && mTint.canApplyTheme())
1940e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mStrokeColors != null && mStrokeColors.canApplyTheme())
1941e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mSolidColors != null && mSolidColors.canApplyTheme())
194245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || super.canApplyTheme();
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
194745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return new GradientDrawable(this, null);
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
194917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1951ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public Drawable newDrawable(@Nullable Resources res) {
1952ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            // If this drawable is being created for a different density,
1953ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            // just create a new constant state and call it a day.
1954ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            final GradientState state;
1955ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            final int density = Drawable.resolveDensity(res, mDensity);
1956ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (density != mDensity) {
1957ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                state = new GradientState(this, res);
1958ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            } else {
1959ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                state = this;
1960ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1961ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1962ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            return new GradientDrawable(state, res);
1963c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
196417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1965c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
1966ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int getChangingConfigurations() {
1967e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mChangingConfigurations
1968e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0)
1969e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0)
1970e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19735f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setShape(@Shape int shape) {
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShape = shape;
1975e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19785f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientType(@GradientType int gradient) {
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradient = gradient;
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setGradientCenter(float x, float y) {
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterX = x;
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterY = y;
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19875f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientColors(@Nullable int[] colors) {
1988e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = colors;
1989e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = null;
1990e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
19918bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        }
1992519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
19935f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setSolidColors(@Nullable ColorStateList colors) {
1994e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = null;
1995e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = colors;
1996e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
1997e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
1998e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
1999e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        private void computeOpacity() {
2000c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = false;
2001c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = false;
200239824f685c33f8aabbe9526b4cc79b7411e8b37fRaph Levien
2003e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors != null) {
2004e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                for (int i = 0; i < mGradientColors.length; i++) {
2005e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    if (!isOpaque(mGradientColors[i])) {
2006e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                        return;
2007e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                    }
2008e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                }
2009e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            }
2010e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
201122cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            // An unfilled shape is not opaque over bounds or shape
2012e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors == null && mSolidColors == null) {
201322cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase                return;
201422cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            }
201522cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase
2016c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // Colors are opaque, so opaqueOverShape=true,
2017c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = true;
2018c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // and opaqueOverBounds=true if shape fills bounds
2019c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = mShape == RECTANGLE
2020c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadius <= 0
2021c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadiusArray == null;
2022e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
2023e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20245f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setStroke(int width, @Nullable ColorStateList colors, float dashWidth,
20255f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                float dashGap) {
2026a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            mStrokeWidth = width;
2027e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mStrokeColors = colors;
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashWidth = dashWidth;
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashGap = dashGap;
2030e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadius(float radius) {
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radius < 0) {
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                radius = 0;
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = null;
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2040e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadii(float[] radii) {
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = radii;
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radii == null) {
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRadius = 0;
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2047e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setSize(int width, int height) {
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = width;
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = height;
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20535f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientRadius(float gradientRadius, @RadiusType int type) {
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradientRadius = gradientRadius;
2055b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette            mGradientRadiusType = type;
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    static boolean isOpaque(int color) {
2060888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return ((color >> 24) & 0xff) == 0xff;
2061888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
2062888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
206352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
206452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Creates a new themed GradientDrawable based on the specified constant state.
206552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * <p>
206652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * The resulting drawable is guaranteed to have a new constant state.
206752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     *
206852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * @param state Constant state from which the drawable inherits
206952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
2070ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    private GradientDrawable(@NonNull GradientState state, @Nullable Resources res) {
207117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        mGradientState = state;
207252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
207345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(res);
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
207645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void updateLocalState(Resources res) {
207745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final GradientState state = mGradientState;
207845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
2079e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null) {
2080519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int[] currentState = getState();
2081e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int stateColor = state.mSolidColors.getColorForState(currentState, 0);
2082519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            mFillPaint.setColor(stateColor);
2083e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        } else if (state.mGradientColors == null) {
2084cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // If we don't have a solid color and we don't have a gradient,
2085cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // the app is stroking the shape, set the color to the default
2086cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // value of state.mSolidColor
2087cf8675ee176a375f873792684d38a47f78348dffRomain Guy            mFillPaint.setColor(0);
20884d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette        } else {
20894d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            // Otherwise, make sure the fill alpha is maxed out.
20904d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            mFillPaint.setColor(Color.BLACK);
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
209217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
20939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPadding = state.mPadding;
209417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state.mStrokeWidth >= 0) {
20966a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStyle(Paint.Style.STROKE);
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStrokeWidth(state.mStrokeWidth);
209917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2100e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (state.mStrokeColors != null) {
2101083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                final int[] currentState = getState();
2102e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int strokeStateColor = state.mStrokeColors.getColorForState(
2103083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                        currentState, 0);
2104083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                mStrokePaint.setColor(strokeStateColor);
2105083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette            }
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mStrokeDashWidth != 0.0f) {
210817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                final DashPathEffect e = new DashPathEffect(
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0);
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setPathEffect(e);
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21133ad771b384b55bc0b9ee9519f457ea7093bb0b74Alan Viverette
2114daec594370f0e47bf07d0c9c968e3c5dfedf0bb5Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
211545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mGradientIsDirty = true;
211645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
211745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        state.computeOpacity();
21189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2120