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    /**
478daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Sets the position of the center of the gradient as a fraction of the
479daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * width and height.
480daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <p>
481daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * The default value is (0.5, 0.5).
48241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
48341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
4848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
48541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
4868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
487daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @param x the X-position of the center of the gradient
488daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @param y the Y-position of the center of the gradient
4898bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
4908bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
4918bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #setGradientType(int)
49241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientCenterX()
49341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientCenterY()
4948bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientCenter(float x, float y) {
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.setGradientCenter(x, y);
4973aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
4989891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
502daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Returns the X-position of the center of the gradient as a fraction of
503daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * the width.
50441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
505daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @return the X-position of the center of the gradient
50641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientCenter(float, float)
50741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
50841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float getGradientCenterX() {
50941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mCenterX;
51041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
51141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
51241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
513daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Returns the Y-position of the center of this gradient as a fraction of
514daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * the height.
51541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
516daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @return the Y-position of the center of the gradient
51741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientCenter(float, float)
51841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
51941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public float getGradientCenterY() {
52041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mCenterY;
52141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
52241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
52341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
52441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the radius of the gradient. The radius is honored only when the
52541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * gradient type is set to {@link #RADIAL_GRADIENT}.
52641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
52741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing this property will affect all instances
5288bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
52941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
5308bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
53141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param gradientRadius the radius of the gradient in pixels
5328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
5338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
53417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setGradientType(int)
53541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getGradientRadius()
5368bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGradientRadius(float gradientRadius) {
538861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        mGradientState.setGradientRadius(gradientRadius, TypedValue.COMPLEX_UNIT_PX);
5393aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
5409891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
544861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * Returns the radius of the gradient in pixels. The radius is valid only
545861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     * when the gradient type is set to {@link #RADIAL_GRADIENT}.
546861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     *
54741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the radius of the gradient in pixels
54841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setGradientRadius(float)
549861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette     */
550861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    public float getGradientRadius() {
551861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        if (mGradientState.mGradient != RADIAL_GRADIENT) {
552861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette            return 0;
553861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        }
554861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
555861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        ensureValidRect();
556861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette        return mGradientRadius;
557861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    }
558861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette
559861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette    /**
560daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Sets whether this drawable's {@code level} property will be used to
561daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * scale the gradient. If a gradient is not used, this property has no
562daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * effect.
56341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
564daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Scaling behavior varies based on gradient type:
565daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <ul>
566daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *     <li>{@link #LINEAR_GRADIENT} adjusts the ending position along the
567daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *         gradient's axis of orientation (see {@link #getOrientation()})
568daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *     <li>{@link #RADIAL_GRADIENT} adjusts the outer radius
569daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *     <li>{@link #SWEEP_GRADIENT} adjusts the ending angle
570daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <ul>
571daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <p>
572daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * The default value for this property is {@code false}.
573daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <p>
574daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <strong>Note</strong>: This property corresponds to the
575daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * {@code android:useLevel} attribute on the inner {@code &lt;gradient&gt;}
576daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * tag, NOT the {@code android:useLevel} attribute on the outer
577daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * {@code &lt;shape&gt;} tag. For example,
578daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <pre>{@code
579daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <shape ...>
580daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *     <gradient
581daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *         ...
582daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *         android:useLevel="true" />
583daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * </shape>
584daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * }</pre><p>
585daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * <strong>Note</strong>: Changing this property will affect all instances
5868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
58741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing this property.
5888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
589daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @param useLevel {@code true} if the gradient should be scaled based on
590daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     *                 level, {@code false} otherwise
5918bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
5928bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
5930b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette     * @see #setLevel(int)
5940b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette     * @see #getLevel()
5955f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette     * @see #getUseLevel()
596daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
5978bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setUseLevel(boolean useLevel) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mGradientState.mUseLevel = useLevel;
6003aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
6019891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
60317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
60441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
605daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * Returns whether this drawable's {@code level} property will be used to
606daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * scale the gradient.
60741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
608daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @return {@code true} if the gradient should be scaled based on level,
60941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *         {@code false} otherwise
61041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setUseLevel(boolean)
611daec5506c45ff0677678fde0732b199cb071250dAlan Viverette     * @attr ref android.R.styleable#GradientDrawableGradient_useLevel
61241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
6135f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public boolean getUseLevel() {
61441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mUseLevel;
61541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
61641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int modulateAlpha(int alpha) {
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int scale = mAlpha + (mAlpha >> 7);
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return alpha * scale >> 8;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
6238bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * Returns the orientation of the gradient defined in this drawable.
62441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
62541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the orientation of the gradient defined in this drawable
62641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setOrientation(Orientation)
6278bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
6288bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public Orientation getOrientation() {
6298bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        return mGradientState.mOrientation;
6308bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
6328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
63341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Sets the orientation of the gradient defined in this drawable.
63441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
63541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing orientation will affect all instances
6368bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * of a drawable loaded from a resource. It is recommended to invoke
63741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing the orientation.
63817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
63941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @param orientation the desired orientation (angle) of the gradient
64017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     *
64117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #mutate()
64241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getOrientation()
6438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
6448bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    public void setOrientation(Orientation orientation) {
6458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        mGradientState.mOrientation = orientation;
6463aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
6478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
6488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
6508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
651e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Sets the colors used to draw the gradient.
652e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
653e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * Each color is specified as an ARGB integer and the array must contain at
654e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * least 2 colors.
655e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <p>
656e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * <strong>Note</strong>: changing colors will affect all instances of a
657e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * drawable loaded from a resource. It is recommended to invoke
658e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * {@link #mutate()} before changing the colors.
6598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
660e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette     * @param colors an array containing 2 or more ARGB colors
6618bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
66217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColor(int)
6638bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
66480756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColors(@ColorInt int[] colors) {
665e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setGradientColors(colors);
6663aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
6678bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        invalidateSelf();
6688bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    }
6698bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
67041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
67141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the colors used to draw the gradient, or {@code null} if the
67241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * gradient is drawn using a single color or no colors.
67341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
67441551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the colors used to draw the gradient, or {@code null}
67541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColors(int[] colors)
67641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
67741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    @Nullable
67841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public int[] getColors() {
6795f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        return mGradientState.mGradientColors == null ?
6805f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                null : mGradientState.mGradientColors.clone();
68141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
68241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
68416f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette    public void draw(Canvas canvas) {
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!ensureValidRect()) {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // nothing to draw
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // remember the alpha values, in case we temporarily overwrite them
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // when we modulate them with mAlpha
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevFillAlpha = mFillPaint.getAlpha();
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int prevStrokeAlpha = mStrokePaint != null ? mStrokePaint.getAlpha() : 0;
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // compute the modulate alpha values
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currFillAlpha = modulateAlpha(prevFillAlpha);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
698e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null &&
699e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                mStrokePaint.getStrokeWidth() > 0;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean haveFill = currFillAlpha > 0;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final GradientState st = mGradientState;
70243027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter;
70343027b7bca554818cc4223389747d661819d5706Alan Viverette
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  we need a layer iff we're drawing both a fill and stroke, and the
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroke is non-opaque, and our shapetype actually supports
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fill+stroke. Otherwise we can just draw the stroke (if any) on top
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            of the fill (if any) without worrying about blending artifacts.
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         */
70943027b7bca554818cc4223389747d661819d5706Alan Viverette        final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
71043027b7bca554818cc4223389747d661819d5706Alan Viverette                 currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null);
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        /*  Drawing with a layer is slower than direct drawing, but it
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            allows us to apply paint effects like alpha and colorfilter to
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            the result of multiple separate draws. In our case, if the user
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            asks for a non-opaque alpha value (via setAlpha), and we're
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            stroking, then we need to apply the alpha AFTER we've drawn
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            both the fill and the stroke.
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        */
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLayerPaint == null) {
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLayerPaint = new Paint();
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
72307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mLayerPaint.setDither(st.mDither);
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayerPaint.setAlpha(mAlpha);
72543027b7bca554818cc4223389747d661819d5706Alan Viverette            mLayerPaint.setColorFilter(colorFilter);
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float rad = mStrokePaint.getStrokeWidth();
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.saveLayer(mRect.left - rad, mRect.top - rad,
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                             mRect.right + rad, mRect.bottom + rad,
7301e5d428b3f8cbe2132d6b85f7cc6ad5212a986dcChris Craik                             mLayerPaint);
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // don't perform the filter in our individual paints
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // since the layer will do it for us
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setColorFilter(null);
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setColorFilter(null);
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*  if we're not using a layer, apply the dither/filter to our
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                individual paints
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            */
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(currFillAlpha);
74107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mFillPaint.setDither(st.mDither);
74243027b7bca554818cc4223389747d661819d5706Alan Viverette            mFillPaint.setColorFilter(colorFilter);
743e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (colorFilter != null && st.mSolidColors == null) {
744813680780f365648b39873fa26dfae0123d51aedChet Haase                mFillPaint.setColor(mAlpha << 24);
74541c769d9a8858ad20b0a6ed942a1cea19ba59d2dRomain Guy            }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(currStrokeAlpha);
74807c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette                mStrokePaint.setDither(st.mDither);
74943027b7bca554818cc4223389747d661819d5706Alan Viverette                mStrokePaint.setColorFilter(colorFilter);
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
752e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (st.mShape) {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RECTANGLE:
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mRadiusArray != null) {
756e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(mPath, mFillPaint);
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawPath(mPath, mStrokePaint);
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
76161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else if (st.mRadius > 0.0f) {
7624e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // since the caller is only giving us 1 value, we will force
7634e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // it to be square if the rect is too small in one dimension
7644e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // to show it. If we did nothing, Skia would clamp the rad
76561c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    // independently along each axis, giving us a thin ellipse
7664e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed                    // if the rect were very wide but not very tall
767b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    float rad = Math.min(st.mRadius,
768b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(mRect.width(), mRect.height()) * 0.5f);
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawRoundRect(mRect, rad, rad, mFillPaint);
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (haveStroke) {
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        canvas.drawRoundRect(mRect, rad, rad, mStrokePaint);
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
77361c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                } else {
77443027b7bca554818cc4223389747d661819d5706Alan Viverette                    if (mFillPaint.getColor() != 0 || colorFilter != null ||
775cf8675ee176a375f873792684d38a47f78348dffRomain Guy                            mFillPaint.getShader() != null) {
776cf8675ee176a375f873792684d38a47f78348dffRomain Guy                        canvas.drawRect(mRect, mFillPaint);
777cf8675ee176a375f873792684d38a47f78348dffRomain Guy                    }
77861c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    if (haveStroke) {
77961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                        canvas.drawRect(mRect, mStrokePaint);
78061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy                    }
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case OVAL:
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawOval(mRect, mFillPaint);
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawOval(mRect, mStrokePaint);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LINE: {
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                RectF r = mRect;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                float y = r.centerY();
79271b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                if (haveStroke) {
79371b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                    canvas.drawLine(r.left, y, r.right, y, mStrokePaint);
79471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette                }
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case RING:
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Path path = buildRing(st);
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                canvas.drawPath(path, mFillPaint);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (haveStroke) {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    canvas.drawPath(path, mStrokePaint);
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
80517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (useLayer) {
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            canvas.restore();
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFillPaint.setAlpha(prevFillAlpha);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (haveStroke) {
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setAlpha(prevStrokeAlpha);
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
815e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
816e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    private void buildPathIfDirty() {
817e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        final GradientState st = mGradientState;
8183aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mPathIsDirty) {
8193aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            ensureValidRect();
820e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.reset();
821e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik            mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
8223aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mPathIsDirty = false;
823e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik        }
824e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik    }
825e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Path buildRing(GradientState st) {
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = false;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8300b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette        float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;
83117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF bounds = new RectF(mRect);
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float x = bounds.width() / 2.0f;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float y = bounds.height() / 2.0f;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float thickness = st.mThickness != -1 ?
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mThickness : bounds.width() / st.mThicknessRatio;
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // inner radius
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float radius = st.mInnerRadius != -1 ?
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                st.mInnerRadius : bounds.width() / st.mInnerRadiusRatio;
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RectF innerBounds = new RectF(bounds);
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        innerBounds.inset(x - radius, y - radius);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds = new RectF(innerBounds);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        bounds.inset(-thickness, -thickness);
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRingPath == null) {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRingPath = new Path();
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
852b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            mRingPath.reset();
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Path ringPath = mRingPath;
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // arcTo treats the sweep angle mod 360, so check for that, since we
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // think 360 means draw the entire oval
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (sweep < 360 && sweep > -360) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.setFillType(Path.FillType.EVEN_ODD);
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner top
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.moveTo(x + radius, y);
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer top
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.lineTo(x + radius + thickness, y);
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // outer arc
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(bounds, 0.0f, sweep, false);
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // inner arc
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.arcTo(innerBounds, sweep, -sweep, false);
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.close();
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // add the entire ovals
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(bounds, Path.Direction.CW);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ringPath.addOval(innerBounds, Path.Direction.CCW);
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ringPath;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy    /**
87941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Changes this drawable to use a single color instead of a gradient.
88041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <p>
88141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * <strong>Note</strong>: changing color will affect all instances of a
88241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * drawable loaded from a resource. It is recommended to invoke
88341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * {@link #mutate()} before changing the color.
8848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
8858bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @param argb The color used to fill the shape
8868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     *
8878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     * @see #mutate()
88817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette     * @see #setColors(int[])
88941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getColor
8908bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy     */
89180756e38882720860db52f1fcc21fa1505a02abfTor Norbye    public void setColor(@ColorInt int argb) {
892e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(ColorStateList.valueOf(argb));
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFillPaint.setColor(argb);
8949891e1fce5f29d0421d34aa481037417bd70853dChet Haase        invalidateSelf();
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
897519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    /**
898519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * Changes this drawable to use a single color state list instead of a
8997c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * gradient. Calling this method with a null argument will clear the color
9007c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * and is equivalent to calling {@link #setColor(int)} with the argument
9017c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette     * {@link Color#TRANSPARENT}.
902519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <p>
903519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * <strong>Note</strong>: changing color will affect all instances of a
904519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * drawable loaded from a resource. It is recommended to invoke
905519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * {@link #mutate()} before changing the color.</p>
906519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     *
907519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @param colorStateList The color state list used to fill the shape
90841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
909519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     * @see #mutate()
91041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #getColor
911519494e207322581075c8ea884fde9d33bb9209eAlan Viverette     */
9125f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setColor(@Nullable ColorStateList colorStateList) {
913e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        mGradientState.setSolidColors(colorStateList);
91440df78153987409dbf299b84da9784b69029e184Alan Viverette        final int color;
9157c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        if (colorStateList == null) {
91640df78153987409dbf299b84da9784b69029e184Alan Viverette            color = Color.TRANSPARENT;
9177c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        } else {
91840df78153987409dbf299b84da9784b69029e184Alan Viverette            final int[] stateSet = getState();
91940df78153987409dbf299b84da9784b69029e184Alan Viverette            color = colorStateList.getColorForState(stateSet, 0);
9207c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette        }
92140df78153987409dbf299b84da9784b69029e184Alan Viverette        mFillPaint.setColor(color);
92240df78153987409dbf299b84da9784b69029e184Alan Viverette        invalidateSelf();
923519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
924519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
92541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    /**
92641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * Returns the color state list used to fill the shape, or {@code null} if
92741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * the shape is filled with a gradient or has no fill color.
92841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
92941551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @return the color state list used to fill this gradient, or {@code null}
93041551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     *
93141551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColor(int)
93241551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     * @see #setColor(ColorStateList)
93341551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette     */
9345f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Nullable
93541551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    public ColorStateList getColor() {
93641551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette        return mGradientState.mSolidColors;
93741551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette    }
93841551849e698129d4bd8861a1de9cb58f1300ec5Alan Viverette
939519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
94012b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette    protected boolean onStateChange(int[] stateSet) {
941a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        boolean invalidateSelf = false;
942a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
943a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
944e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        final ColorStateList solidColors = s.mSolidColors;
945e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (solidColors != null) {
946e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int newColor = solidColors.getColorForState(stateSet, 0);
947519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int oldColor = mFillPaint.getColor();
948519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            if (oldColor != newColor) {
949519494e207322581075c8ea884fde9d33bb9209eAlan Viverette                mFillPaint.setColor(newColor);
950616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                invalidateSelf = true;
951a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            }
952a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
953a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
954616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        final Paint strokePaint = mStrokePaint;
955616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette        if (strokePaint != null) {
956e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final ColorStateList strokeColors = s.mStrokeColors;
957e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (strokeColors != null) {
958e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int newColor = strokeColors.getColorForState(stateSet, 0);
959e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int oldColor = strokePaint.getColor();
960e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (oldColor != newColor) {
961e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    strokePaint.setColor(newColor);
962616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                    invalidateSelf = true;
963616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette                }
964519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            }
965519494e207322581075c8ea884fde9d33bb9209eAlan Viverette        }
966519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
96743027b7bca554818cc4223389747d661819d5706Alan Viverette        if (s.mTint != null && s.mTintMode != null) {
96843027b7bca554818cc4223389747d661819d5706Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode);
96943027b7bca554818cc4223389747d661819d5706Alan Viverette            invalidateSelf = true;
97043027b7bca554818cc4223389747d661819d5706Alan Viverette        }
97143027b7bca554818cc4223389747d661819d5706Alan Viverette
972a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        if (invalidateSelf) {
973a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            invalidateSelf();
974a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            return true;
975a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        }
976a211dd28b93473c452d68432c602d5209b01c178Alan Viverette
977a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return false;
978519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
979519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
980519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    @Override
981519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    public boolean isStateful() {
982a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        final GradientState s = mGradientState;
983a211dd28b93473c452d68432c602d5209b01c178Alan Viverette        return super.isStateful()
984e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mSolidColors != null && s.mSolidColors.isStateful())
985e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                || (s.mStrokeColors != null && s.mStrokeColors.isStateful())
98643027b7bca554818cc4223389747d661819d5706Alan Viverette                || (s.mTint != null && s.mTint.isStateful());
987519494e207322581075c8ea884fde9d33bb9209eAlan Viverette    }
988519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
990ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette    public @Config int getChangingConfigurations() {
991e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return super.getChangingConfigurations() | mGradientState.getChangingConfigurations();
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9938bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAlpha(int alpha) {
9969891e1fce5f29d0421d34aa481037417bd70853dChet Haase        if (alpha != mAlpha) {
9979891e1fce5f29d0421d34aa481037417bd70853dChet Haase            mAlpha = alpha;
9989891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
9999891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1003b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    public int getAlpha() {
1004b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase        return mAlpha;
1005b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    }
1006b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase
1007b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase    @Override
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDither(boolean dither) {
100907c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        if (dither != mGradientState.mDither) {
101007c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette            mGradientState.mDither = dither;
10119891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
10129891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10165f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    @Nullable
101738b5f597de96cd892add9017dc810212f549bf68John Spurlock    public ColorFilter getColorFilter() {
101838b5f597de96cd892add9017dc810212f549bf68John Spurlock        return mColorFilter;
101938b5f597de96cd892add9017dc810212f549bf68John Spurlock    }
102038b5f597de96cd892add9017dc810212f549bf68John Spurlock
102138b5f597de96cd892add9017dc810212f549bf68John Spurlock    @Override
10225f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setColorFilter(@Nullable ColorFilter colorFilter) {
1023bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik        if (colorFilter != mColorFilter) {
1024bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik            mColorFilter = colorFilter;
10259891e1fce5f29d0421d34aa481037417bd70853dChet Haase            invalidateSelf();
10269891e1fce5f29d0421d34aa481037417bd70853dChet Haase        }
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10305f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setTintList(@Nullable ColorStateList tint) {
103143027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTint = tint;
103243027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode);
103343027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
103443027b7bca554818cc4223389747d661819d5706Alan Viverette    }
103543027b7bca554818cc4223389747d661819d5706Alan Viverette
103643027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
10375f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette    public void setTintMode(@Nullable PorterDuff.Mode tintMode) {
103843027b7bca554818cc4223389747d661819d5706Alan Viverette        mGradientState.mTintMode = tintMode;
103943027b7bca554818cc4223389747d661819d5706Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode);
104043027b7bca554818cc4223389747d661819d5706Alan Viverette        invalidateSelf();
104143027b7bca554818cc4223389747d661819d5706Alan Viverette    }
104243027b7bca554818cc4223389747d661819d5706Alan Viverette
104343027b7bca554818cc4223389747d661819d5706Alan Viverette    @Override
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOpacity() {
1045888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ?
10460a1c6f021be032f5aecb341c2794efb06c0a8a0dAlan Viverette                PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT;
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onBoundsChange(Rect r) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onBoundsChange(r);
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRingPath = null;
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
10543aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10580b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette    protected boolean onLevelChange(int level) {
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onLevelChange(level);
10603aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        mGradientIsDirty = true;
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPathIsDirty = true;
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        invalidateSelf();
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10673aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase     * This checks mGradientIsDirty, and if it is true, recomputes both our drawing
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle (mRect) and the gradient itself, since it depends on our
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * rectangle too.
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if the resulting rectangle is not empty, false otherwise
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean ensureValidRect() {
10733aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase        if (mGradientIsDirty) {
10743aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase            mGradientIsDirty = false;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect bounds = getBounds();
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float inset = 0;
107817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mStrokePaint != null) {
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                inset = mStrokePaint.getStrokeWidth() * 0.5f;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final GradientState st = mGradientState;
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRect.set(bounds.left + inset, bounds.top + inset,
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                      bounds.right - inset, bounds.bottom - inset);
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1088e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int[] gradientColors = st.mGradientColors;
1089e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (gradientColors != null) {
1090e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final RectF r = mRect;
1091e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final float x0, x1, y0, y1;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (st.mGradient == LINEAR_GRADIENT) {
10940b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    switch (st.mOrientation) {
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TOP_BOTTOM:
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.bottom;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case TR_BL:
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.bottom;
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case RIGHT_LEFT:
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.top;
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = y0;
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BR_TL:
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.right;           y0 = r.bottom;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.left;    y1 = level * r.top;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BOTTOM_TOP:
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = x0;                y1 = level * r.top;
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case BL_TR:
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.bottom;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.top;
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case LEFT_RIGHT:
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = y0;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    default:/* TL_BR */
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x0 = r.left;            y0 = r.top;
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        x1 = level * r.right;   y1 = level * r.bottom;
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
1131e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            gradientColors, st.mPositions, Shader.TileMode.CLAMP));
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == RADIAL_GRADIENT) {
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1136861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    float radius = st.mGradientRadius;
1137b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
1138b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // Fall back to parent width or height if intrinsic
1139b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // size is not specified.
1140b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float width = st.mWidth >= 0 ? st.mWidth : r.width();
1141b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        final float height = st.mHeight >= 0 ? st.mHeight : r.height();
1142b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        radius *= Math.min(width, height);
1143b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    } else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) {
1144861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                        radius *= Math.min(r.width(), r.height());
1145861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
1146b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1147861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    if (st.mUseLevel) {
11480b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                        radius *= getLevel() / 10000.0f;
1149861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    }
1150b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1151861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mGradientRadius = radius;
1152b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1153b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                    if (radius <= 0) {
1154b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // We can't have a shader with non-positive radius, so
1155b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette                        // let's have a very, very small radius.
1156b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                        radius = 0.001f;
1157b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette                    }
1158b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette
1159861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette                    mFillPaint.setShader(new RadialGradient(
1160e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                            x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP));
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (st.mGradient == SWEEP_GRADIENT) {
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    x0 = r.left + (r.right - r.left) * st.mCenterX;
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1165e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    int[] tempColors = gradientColors;
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    float[] tempPositions = null;
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (st.mUseLevel) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempColors = st.mTempColors;
1170e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        final int length = gradientColors.length;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempColors == null || tempColors.length != length + 1) {
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempColors = st.mTempColors = new int[length + 1];
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
1174e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        System.arraycopy(gradientColors, 0, tempColors, 0, length);
1175e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                        tempColors[length] = gradientColors[length - 1];
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions = st.mTempPositions;
117852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        final float fraction = 1.0f / (length - 1);
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (tempPositions == null || tempPositions.length != length + 1) {
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions = st.mTempPositions = new float[length + 1];
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11830b6cfe22fda3396b4790ac79fc90488bec4a49a4Alan Viverette                        final float level = getLevel() / 10000.0f;
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        for (int i = 0; i < length; i++) {
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            tempPositions[i] = i * fraction * level;
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        tempPositions[length] = 1.0f;
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
11914d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                }
11924d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette
11934d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // If we don't have a solid color, the alpha channel must be
11944d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                // maxed out so that alpha modulation works correctly.
1195e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                if (st.mSolidColors == null) {
11964d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette                    mFillPaint.setColor(Color.BLACK);
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return !mRect.isEmpty();
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1204ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
1205ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            @NonNull AttributeSet attrs, @Nullable Theme theme)
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws XmlPullParserException, IOException {
1207ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        super.inflate(r, parser, attrs, theme);
1208ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1209ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        mGradientState.setDensity(Drawable.resolveDensity(r, 0));
1210ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
121152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawable);
121217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        updateStateFromTypedArray(a);
121352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        a.recycle();
121452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
121552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        inflateChildElements(r, parser, attrs, theme);
121652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
121745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(r);
121852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
121952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
122052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
1221ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    public void applyTheme(@NonNull Theme t) {
122252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        super.applyTheme(t);
122352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
122452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
122517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state == null) {
122617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            return;
122752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
122852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1229ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        state.setDensity(Drawable.resolveDensity(t.getResources(), 0));
1230ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
123117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        if (state.mThemeAttrs != null) {
123217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            final TypedArray a = t.resolveAttributes(
123317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette                    state.mThemeAttrs, R.styleable.GradientDrawable);
123417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            updateStateFromTypedArray(a);
123517cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            a.recycle();
123617cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        }
123752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
123845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mTint != null && state.mTint.canApplyTheme()) {
1239e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mTint = state.mTint.obtainForTheme(t);
124045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
124145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1242e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) {
1243e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mSolidColors = state.mSolidColors.obtainForTheme(t);
124445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
124545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
1246e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) {
1247e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mStrokeColors = state.mStrokeColors.obtainForTheme(t);
124845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
124945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
125017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        applyThemeChildElements(t);
125152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
125245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(t.getResources());
125352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
125452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
125552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
125652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Updates the constant state from the values in the typed array.
125752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
125852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void updateStateFromTypedArray(TypedArray a) {
125952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState state = mGradientState;
126052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
12618e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
12628e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
12638e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
126417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
126517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
126652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
126717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape);
126807c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither);
126952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
127052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (state.mShape == RING) {
127117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mInnerRadius = a.getDimensionPixelSize(
127217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_innerRadius, state.mInnerRadius);
127352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
127417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mInnerRadius == -1) {
127552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mInnerRadiusRatio = a.getFloat(
127617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_innerRadiusRatio, state.mInnerRadiusRatio);
127752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
127852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
127917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mThickness = a.getDimensionPixelSize(
128017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_thickness, state.mThickness);
128152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
128217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            if (state.mThickness == -1) {
128352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                state.mThicknessRatio = a.getFloat(
128417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                        R.styleable.GradientDrawable_thicknessRatio, state.mThicknessRatio);
128552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
128652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
128717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            state.mUseLevelForShape = a.getBoolean(
128817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape);
128952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
129043027b7bca554818cc4223389747d661819d5706Alan Viverette
129143027b7bca554818cc4223389747d661819d5706Alan Viverette        final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1);
129243027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tintMode != -1) {
129343027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN);
129443027b7bca554818cc4223389747d661819d5706Alan Viverette        }
129543027b7bca554818cc4223389747d661819d5706Alan Viverette
129643027b7bca554818cc4223389747d661819d5706Alan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint);
129743027b7bca554818cc4223389747d661819d5706Alan Viverette        if (tint != null) {
129843027b7bca554818cc4223389747d661819d5706Alan Viverette            state.mTint = tint;
129943027b7bca554818cc4223389747d661819d5706Alan Viverette        }
130087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
130187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetLeft = a.getDimensionPixelSize(
130287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetLeft, state.mOpticalInsets.left);
130387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetTop = a.getDimensionPixelSize(
130487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetTop, state.mOpticalInsets.top);
130587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetRight = a.getDimensionPixelSize(
130687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetRight, state.mOpticalInsets.right);
130787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetBottom = a.getDimensionPixelSize(
130887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.GradientDrawable_opticalInsetBottom, state.mOpticalInsets.bottom);
130987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        state.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom);
131052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
131152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
131252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    @Override
131352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    public boolean canApplyTheme() {
1314d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
131552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
131652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
131752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void applyThemeChildElements(Theme t) {
131817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
131952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
132017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSize != null) {
132117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
132217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSize, R.styleable.GradientDrawableSize);
132317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSize(a);
132452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
132552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
132652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
132717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrGradient != null) {
132817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
132917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrGradient, R.styleable.GradientDrawableGradient);
133017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            try {
133117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(t.getResources(), a);
133217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } catch (XmlPullParserException e) {
1333c078c605ab904b0e4a5d793cbeffd78c340f2816Alan Viverette                rethrowAsRuntimeException(e);
133417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            } finally {
133517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.recycle();
133617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            }
133752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
133852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
133917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrSolid != null) {
134017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
134117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrSolid, R.styleable.GradientDrawableSolid);
134217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableSolid(a);
134352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
134452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
134552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
134617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrStroke != null) {
134717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
134817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrStroke, R.styleable.GradientDrawableStroke);
134917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawableStroke(a);
135052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
135152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
135252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
135317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrCorners != null) {
135417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
135517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrCorners, R.styleable.DrawableCorners);
135617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateDrawableCorners(a);
135752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
135852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
135952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
136017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (st.mAttrPadding != null) {
136117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedArray a = t.resolveAttributes(
136217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    st.mAttrPadding, R.styleable.GradientDrawablePadding);
136317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            updateGradientDrawablePadding(a);
136452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            a.recycle();
136552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
136652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
136752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
136852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
136952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            Theme theme) throws XmlPullParserException, IOException {
137052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        TypedArray a;
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int type;
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1373ed7894352f8addfe3d0da75cc7fe8bc6fef201dcRomain Guy        final int innerDepth = parser.getDepth() + 1;
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int depth;
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               && ((depth=parser.getDepth()) >= innerDepth
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                       || type != XmlPullParser.END_TAG)) {
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (type != XmlPullParser.START_TAG) {
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (depth > innerDepth) {
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
138552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String name = parser.getName();
138717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (name.equals("size")) {
138917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSize);
139017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSize(a);
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("gradient")) {
139317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableGradient);
139417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableGradient(r, a);
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("solid")) {
139717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSolid);
139817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableSolid(a);
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("stroke")) {
140117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableStroke);
140217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawableStroke(a);
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("corners")) {
140517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.DrawableCorners);
140617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateDrawableCorners(a);
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (name.equals("padding")) {
140917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawablePadding);
141017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                updateGradientDrawablePadding(a);
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                a.recycle();
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Log.w("drawable", "Bad element under <shape>: " + name);
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
141552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
141652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
141752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
141817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawablePadding(TypedArray a) {
141917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
142052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
14218e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14228e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14238e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
142452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
142517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrPadding = a.extractThemeAttrs();
142617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1427982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        if (st.mPadding == null) {
1428982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette            st.mPadding = new Rect();
1429982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette        }
1430982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette
143117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final Rect pad = st.mPadding;
143217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        pad.set(a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_left, pad.left),
143317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_top, pad.top),
143417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_right, pad.right),
143517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_bottom, pad.bottom));
143617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        mPadding = pad;
143752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
1438e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
143917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateDrawableCorners(TypedArray a) {
144017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
144117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14448e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
144517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
144617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrCorners = a.extractThemeAttrs();
144717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
144817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int radius = a.getDimensionPixelSize(
144917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.DrawableCorners_radius, (int) st.mRadius);
145052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        setCornerRadius(radius);
145117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
145217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
145317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topLeftRadius = a.getDimensionPixelSize(
145452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topLeftRadius, radius);
145517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int topRightRadius = a.getDimensionPixelSize(
145652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_topRightRadius, radius);
145717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomLeftRadius = a.getDimensionPixelSize(
145852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomLeftRadius, radius);
145917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final int bottomRightRadius = a.getDimensionPixelSize(
146052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.DrawableCorners_bottomRightRadius, radius);
146152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (topLeftRadius != radius || topRightRadius != radius ||
146252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                bottomLeftRadius != radius || bottomRightRadius != radius) {
146352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // The corner radii are specified in clockwise order (see Path.addRoundRect())
146452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setCornerRadii(new float[] {
146552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topLeftRadius, topLeftRadius,
146652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    topRightRadius, topRightRadius,
146752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomRightRadius, bottomRightRadius,
146852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    bottomLeftRadius, bottomLeftRadius
146952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            });
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
147152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
147252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
147317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableStroke(TypedArray a) {
147417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
147517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14768e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
14778e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
14788e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
14798e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
148017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrStroke = a.extractThemeAttrs();
148117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
14823b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // We have an explicit stroke defined, so the default stroke width
14833b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        // must be at least 0 or the current stroke width.
14843b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette        final int defaultStrokeWidth = Math.max(0, st.mStrokeWidth);
148552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int width = a.getDimensionPixelSize(
14863b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                R.styleable.GradientDrawableStroke_width, defaultStrokeWidth);
148752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final float dashWidth = a.getDimension(
148817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_dashWidth, st.mStrokeDashWidth);
148917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
149017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        ColorStateList colorStateList = a.getColorStateList(
149117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableStroke_color);
149217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList == null) {
1493e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            colorStateList = st.mStrokeColors;
149417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
149517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
149652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (dashWidth != 0.0f) {
149752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            final float dashGap = a.getDimension(
149817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                    R.styleable.GradientDrawableStroke_dashGap, st.mStrokeDashGap);
149952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList, dashWidth, dashGap);
150052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
150152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            setStroke(width, colorStateList);
150252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
150352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
150452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
150517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSolid(TypedArray a) {
15068e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final GradientState st = mGradientState;
15078e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
15088e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
15098e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
15108e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
15118e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Extract the theme attributes, if any.
15128e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mAttrSolid = a.extractThemeAttrs();
151317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
151452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final ColorStateList colorStateList = a.getColorStateList(
151552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableSolid_color);
151617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        if (colorStateList != null) {
151717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            setColor(colorStateList);
151817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        }
151952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
152052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
152117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableGradient(Resources r, TypedArray a)
152252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            throws XmlPullParserException {
152352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final GradientState st = mGradientState;
152417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
15258e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
15268e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
15278e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
152817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // Extract the theme attributes, if any.
152917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrGradient = a.extractThemeAttrs();
153017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
153117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterX = getFloatOrFraction(
153217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerX, st.mCenterX);
153317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mCenterY = getFloatOrFraction(
153417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                a, R.styleable.GradientDrawableGradient_centerY, st.mCenterY);
153517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mUseLevel = a.getBoolean(
153617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_useLevel, st.mUseLevel);
153717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mGradient = a.getInt(
153817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                R.styleable.GradientDrawableGradient_type, st.mGradient);
153917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
154017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        // TODO: Update these to be themeable.
154152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int startColor = a.getColor(
154252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_startColor, 0);
154352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final boolean hasCenterColor = a.hasValue(
154452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor);
154552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int centerColor = a.getColor(
154652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_centerColor, 0);
154752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        final int endColor = a.getColor(
154852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                R.styleable.GradientDrawableGradient_endColor, 0);
154952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
155052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (hasCenterColor) {
1551e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[3];
1552e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1553e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = centerColor;
1554e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[2] = endColor;
155517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
155652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions = new float[3];
155752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[0] = 0.0f;
155852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            // Since 0.5f is default value, try to take the one that isn't 0.5f
155952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY;
156052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            st.mPositions[2] = 1f;
156152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
1562e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors = new int[2];
1563e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[0] = startColor;
1564e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            st.mGradientColors[1] = endColor;
156552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
156652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
156752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        if (st.mGradient == LINEAR_GRADIENT) {
156817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
156952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            angle %= 360;
157052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
157152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (angle % 45 != 0) {
157252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(a.getPositionDescription()
157352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'angle' attribute to "
157452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "be a multiple of 45");
157552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
157652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
157717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            st.mAngle = angle;
157817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
157952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            switch (angle) {
158052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 0:
158152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.LEFT_RIGHT;
158252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
158352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 45:
158452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BL_TR;
158552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
158652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 90:
158752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BOTTOM_TOP;
158852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
158952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 135:
159052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.BR_TL;
159152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
159252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 180:
159352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.RIGHT_LEFT;
159452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
159552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 225:
159652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TR_BL;
159752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
159852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 270:
159952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TOP_BOTTOM;
160052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
160152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                case 315:
160252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    st.mOrientation = Orientation.TL_BR;
160352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    break;
160452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
160552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        } else {
160617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette            final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
160752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            if (tv != null) {
160852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                final float radius;
16095f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                final @RadiusType int radiusType;
161052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                if (tv.type == TypedValue.TYPE_FRACTION) {
161152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getFraction(1.0f, 1.0f);
161252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
161352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT)
161452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                            & TypedValue.COMPLEX_UNIT_MASK;
161552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) {
161652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION_PARENT;
161752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    } else {
161852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        radiusType = RADIUS_TYPE_FRACTION;
161952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    }
16202efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else if (tv.type == TypedValue.TYPE_DIMENSION) {
162152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radius = tv.getDimension(r.getDisplayMetrics());
162252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
16232efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                } else {
16242efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radius = tv.getFloat();
16252efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette                    radiusType = RADIUS_TYPE_PIXELS;
162652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                }
162752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
162852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadius = radius;
162952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                st.mGradientRadiusType = radiusType;
163052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            } else if (st.mGradient == RADIAL_GRADIENT) {
163152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                throw new XmlPullParserException(
163252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        a.getPositionDescription()
163352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "<gradient> tag requires 'gradientRadius' "
163452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette                        + "attribute with radial type");
163552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette            }
163652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
163752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    }
163852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
163917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette    private void updateGradientDrawableSize(TypedArray a) {
164017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        final GradientState st = mGradientState;
164152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
16428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
16438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        st.mChangingConfigurations |= a.getChangingConfigurations();
16448e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
164552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        // Extract the theme attributes, if any.
164617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mAttrSize = a.extractThemeAttrs();
164717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
164817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mWidth = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_width, st.mWidth);
164917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        st.mHeight = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_height, st.mHeight);
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) {
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedValue tv = a.peekValue(index);
16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        float v = defaultValue;
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (tv != null) {
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean vIsFraction = tv.type == TypedValue.TYPE_FRACTION;
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            v = vIsFraction ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return v;
16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
166117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicWidth() {
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mWidth;
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getIntrinsicHeight() {
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState.mHeight;
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
167117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
167287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    /** @hide */
167387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    @Override
167487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    public Insets getOpticalInsets() {
167587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        return mGradientState.mOpticalInsets;
167687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    }
167787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ConstantState getConstantState() {
16806efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais        mGradientState.mChangingConfigurations = getChangingConfigurations();
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mGradientState;
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1684888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    private boolean isOpaqueForState() {
1685888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        if (mGradientState.mStrokeWidth >= 0 && mStrokePaint != null
1686888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette                && !isOpaque(mStrokePaint.getColor())) {
1687888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1688888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1689888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
16905f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        // Don't check opacity if we're using a gradient, as we've already
16915f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        // checked the gradient opacity in mOpaqueOverShape.
16925f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        if (mGradientState.mGradientColors == null && !isOpaque(mFillPaint.getColor())) {
1693888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette            return false;
1694888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        }
1695888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
1696888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return true;
1697888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
1698888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
170031ba192dd201df2cad96a8c503f730130ab0d80fChris Craik    public void getOutline(Outline outline) {
1701b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final GradientState st = mGradientState;
1702b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        final Rect bounds = getBounds();
1703f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        // only report non-zero alpha if shape being drawn has consistent opacity over shape. Must
1704f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        // either not have a stroke, or have same stroke/fill opacity
1705f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        boolean useFillOpacity = st.mOpaqueOverShape && (mGradientState.mStrokeWidth <= 0
1706f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                || mStrokePaint == null
1707f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                || mStrokePaint.getAlpha() == mFillPaint.getAlpha());
1708f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik        outline.setAlpha(useFillOpacity
1709f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                ? modulateAlpha(mFillPaint.getAlpha()) / 255.0f
1710f3dc7ac7242046d70e4ffee41fd7dbc9b9674ec0Chris Craik                : 0.0f);
1711b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1712b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        switch (st.mShape) {
1713b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            case RECTANGLE:
1714b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadiusArray != null) {
1715e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    buildPathIfDirty();
1716e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                    outline.setConvexPath(mPath);
171731ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                    return;
1718b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
1719e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik
1720b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                float rad = 0;
1721b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                if (st.mRadius > 0.0f) {
1722b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    // clamp the radius based on width & height, matching behavior in draw()
1723b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                    rad = Math.min(st.mRadius,
1724b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                            Math.min(bounds.width(), bounds.height()) * 0.5f);
1725b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik                }
17267979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setRoundRect(bounds, rad);
172731ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
17287979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case OVAL:
17297979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik                outline.setOval(bounds);
173031ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
17317979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik            case LINE:
17323b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // Hairlines (0-width stroke) must have a non-empty outline for
17333b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                // shadows to draw correctly, so we'll use a very small width.
17343b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float halfStrokeWidth = mStrokePaint == null ?
17353b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                        0.0001f : mStrokePaint.getStrokeWidth() * 0.5f;
17363b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final float centerY = bounds.centerY();
17373b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int top = (int) Math.floor(centerY - halfStrokeWidth);
17383b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette                final int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
1739b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1740e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik                outline.setRect(bounds.left, top, bounds.right, bottom);
174131ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                return;
1742b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            default:
174331ba192dd201df2cad96a8c503f730130ab0d80fChris Craik                // TODO: support more complex shapes
1744b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        }
1745b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
1746b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
1747b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    @Override
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Drawable mutate() {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mMutated && super.mutate() == this) {
1750ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientState = new GradientState(mGradientState, null);
175145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            updateLocalState(null);
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mMutated = true;
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return this;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1757727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
1758727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
1759727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
1760727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
1761727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
1762727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
1763727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
1764727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final static class GradientState extends ConstantState {
1766ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int mChangingConfigurations;
17675f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @Shape int mShape = RECTANGLE;
17685f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @GradientType int mGradient = LINEAR_GRADIENT;
176971b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mAngle = 0;
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Orientation mOrientation;
1771e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mSolidColors;
1772e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public ColorStateList mStrokeColors;
17735f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @ColorInt int[] mGradientColors;
17745f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public @ColorInt int[] mTempColors; // no need to copy
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mTempPositions; // no need to copy
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public float[] mPositions;
177771b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public int mStrokeWidth = -1; // if >= 0 use stroking.
177871b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashWidth = 0.0f;
177971b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mStrokeDashGap = 0.0f;
178071b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float mRadius = 0.0f; // use this if mRadiusArray is null
178171b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public float[] mRadiusArray = null;
178271b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette        public Rect mPadding = null;
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mWidth = -1;
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public int mHeight = -1;
178517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO;
178617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public float mThicknessRatio = DEFAULT_THICKNESS_RATIO;
178717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mInnerRadius = -1;
178817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette        public int mThickness = -1;
178907c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette        public boolean mDither = false;
179087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        public Insets mOpticalInsets = Insets.NONE;
179107c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette
1792969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterX = 0.5f;
1793969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mCenterY = 0.5f;
1794969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        float mGradientRadius = 0.5f;
17955f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        @RadiusType int mGradientRadiusType = RADIUS_TYPE_PIXELS;
1796969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevel = false;
1797969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mUseLevelForShape = true;
1798969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette
1799969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverBounds;
1800969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette        boolean mOpaqueOverShape;
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
180243027b7bca554818cc4223389747d661819d5706Alan Viverette        ColorStateList mTint = null;
180343027b7bca554818cc4223389747d661819d5706Alan Viverette        PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE;
180443027b7bca554818cc4223389747d661819d5706Alan Viverette
1805ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        int mDensity = DisplayMetrics.DENSITY_DEFAULT;
1806ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
180752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mThemeAttrs;
180852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSize;
180952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrGradient;
181052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrSolid;
181152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrStroke;
181252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrCorners;
181352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        int[] mAttrPadding;
181452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
1815e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        public GradientState(Orientation orientation, int[] gradientColors) {
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOrientation = orientation;
1817e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            setGradientColors(gradientColors);
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1820ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public GradientState(@NonNull GradientState orig, @Nullable Resources res) {
1821ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mChangingConfigurations = orig.mChangingConfigurations;
1822ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mShape = orig.mShape;
1823ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradient = orig.mGradient;
1824ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAngle = orig.mAngle;
1825ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOrientation = orig.mOrientation;
1826ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mSolidColors = orig.mSolidColors;
1827ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mGradientColors != null) {
1828ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mGradientColors = orig.mGradientColors.clone();
1829562bf17c6c7c5226b2220e27a1543d4a43543d6cPhil Dubach            }
1830ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mPositions != null) {
1831ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPositions = orig.mPositions.clone();
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1833ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeColors = orig.mStrokeColors;
1834ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeWidth = orig.mStrokeWidth;
1835ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeDashWidth = orig.mStrokeDashWidth;
1836ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mStrokeDashGap = orig.mStrokeDashGap;
1837ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mRadius = orig.mRadius;
1838ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mRadiusArray != null) {
1839ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray = orig.mRadiusArray.clone();
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1841ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mPadding != null) {
1842ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding = new Rect(orig.mPadding);
1843ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1844ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mWidth = orig.mWidth;
1845ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mHeight = orig.mHeight;
1846ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mInnerRadiusRatio = orig.mInnerRadiusRatio;
1847ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThicknessRatio = orig.mThicknessRatio;
1848ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mInnerRadius = orig.mInnerRadius;
1849ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThickness = orig.mThickness;
1850ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDither = orig.mDither;
1851ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpticalInsets = orig.mOpticalInsets;
1852ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mCenterX = orig.mCenterX;
1853ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mCenterY = orig.mCenterY;
1854ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientRadius = orig.mGradientRadius;
1855ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mGradientRadiusType = orig.mGradientRadiusType;
1856ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mUseLevel = orig.mUseLevel;
1857ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mUseLevelForShape = orig.mUseLevelForShape;
1858ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpaqueOverBounds = orig.mOpaqueOverBounds;
1859ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mOpaqueOverShape = orig.mOpaqueOverShape;
1860ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mTint = orig.mTint;
1861ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mTintMode = orig.mTintMode;
1862ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mThemeAttrs = orig.mThemeAttrs;
1863ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrSize = orig.mAttrSize;
1864ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrGradient = orig.mAttrGradient;
1865ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrSolid = orig.mAttrSolid;
1866ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrStroke = orig.mAttrStroke;
1867ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrCorners = orig.mAttrCorners;
1868ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mAttrPadding = orig.mAttrPadding;
1869ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1870ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            mDensity = Drawable.resolveDensity(res, orig.mDensity);
1871ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (orig.mDensity != mDensity) {
1872ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                applyDensityScaling(orig.mDensity, mDensity);
1873ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1874ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        }
1875ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1876ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        /**
1877ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * Sets the constant state density.
1878ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * <p>
1879ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * If the density has been previously set, dispatches the change to
1880ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * subclasses so that density-dependent properties may be scaled as
1881ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * necessary.
1882ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         *
1883ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         * @param targetDensity the new constant state density
1884ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette         */
1885ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public final void setDensity(int targetDensity) {
1886ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mDensity != targetDensity) {
1887ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int sourceDensity = mDensity;
1888ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mDensity = targetDensity;
1889ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1890ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                applyDensityScaling(sourceDensity, targetDensity);
1891ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1892ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        }
1893ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1894ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        private void applyDensityScaling(int sourceDensity, int targetDensity) {
1895ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mInnerRadius > 0) {
1896ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mInnerRadius = Drawable.scaleFromDensity(
1897ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mInnerRadius, sourceDensity, targetDensity, true);
1898ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1899ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mThickness > 0) {
1900ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mThickness = Drawable.scaleFromDensity(
1901ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mThickness, sourceDensity, targetDensity, true);
1902ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1903ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mOpticalInsets != Insets.NONE) {
1904ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int left = Drawable.scaleFromDensity(
1905ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.left, sourceDensity, targetDensity, true);
1906ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int top = Drawable.scaleFromDensity(
1907ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.top, sourceDensity, targetDensity, true);
1908ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int right = Drawable.scaleFromDensity(
1909ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.right, sourceDensity, targetDensity, true);
1910ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                final int bottom = Drawable.scaleFromDensity(
1911ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mOpticalInsets.bottom, sourceDensity, targetDensity, true);
1912ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mOpticalInsets = Insets.of(left, top, right, bottom);
1913ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1914ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mPadding != null) {
1915ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.left = Drawable.scaleFromDensity(
1916ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.left, sourceDensity, targetDensity, false);
1917ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.top = Drawable.scaleFromDensity(
1918ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.top, sourceDensity, targetDensity, false);
1919ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.right = Drawable.scaleFromDensity(
1920ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.right, sourceDensity, targetDensity, false);
1921ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mPadding.bottom = Drawable.scaleFromDensity(
1922ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mPadding.bottom, sourceDensity, targetDensity, false);
1923ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1924ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mRadius > 0) {
1925ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadius = Drawable.scaleFromDensity(mRadius, sourceDensity, targetDensity);
1926ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1927ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mRadiusArray != null) {
1928ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[0] = Drawable.scaleFromDensity(
1929ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[0], sourceDensity, targetDensity, true);
1930ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[1] = Drawable.scaleFromDensity(
1931ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[1], sourceDensity, targetDensity, true);
1932ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[2] = Drawable.scaleFromDensity(
1933ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[2], sourceDensity, targetDensity, true);
1934ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mRadiusArray[3] = Drawable.scaleFromDensity(
1935ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        (int) mRadiusArray[3], sourceDensity, targetDensity, true);
1936ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1937ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeWidth > 0) {
1938ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeWidth = Drawable.scaleFromDensity(
1939ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeWidth, sourceDensity, targetDensity, true);
1940ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1941ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeDashWidth > 0) {
1942ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeDashWidth = Drawable.scaleFromDensity(
1943ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeDashGap, sourceDensity, targetDensity);
1944ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1945ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mStrokeDashGap > 0) {
1946ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mStrokeDashGap = Drawable.scaleFromDensity(
1947ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mStrokeDashGap, sourceDensity, targetDensity);
1948ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1949ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mGradientRadiusType == RADIUS_TYPE_PIXELS) {
1950ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mGradientRadius = Drawable.scaleFromDensity(
1951ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                        mGradientRadius, sourceDensity, targetDensity);
1952ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1953ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mWidth > 0) {
1954ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mWidth = Drawable.scaleFromDensity(mWidth, sourceDensity, targetDensity, true);
1955ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1956ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (mHeight > 0) {
1957ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                mHeight = Drawable.scaleFromDensity(mHeight, sourceDensity, targetDensity, true);
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
195952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        }
196052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
196152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        @Override
196252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette        public boolean canApplyTheme() {
196345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mThemeAttrs != null
196445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSize != null || mAttrGradient != null
196545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrSolid != null || mAttrStroke != null
196645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || mAttrCorners != null || mAttrPadding != null
196745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mTint != null && mTint.canApplyTheme())
1968e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mStrokeColors != null && mStrokeColors.canApplyTheme())
1969e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    || (mSolidColors != null && mSolidColors.canApplyTheme())
197045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || super.canApplyTheme();
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public Drawable newDrawable() {
197545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return new GradientDrawable(this, null);
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
197717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1979ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette        public Drawable newDrawable(@Nullable Resources res) {
1980ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            // If this drawable is being created for a different density,
1981ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            // just create a new constant state and call it a day.
1982ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            final GradientState state;
1983ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            final int density = Drawable.resolveDensity(res, mDensity);
1984ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            if (density != mDensity) {
1985ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                state = new GradientState(this, res);
1986ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            } else {
1987ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette                state = this;
1988ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            }
1989ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette
1990ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette            return new GradientDrawable(state, res);
1991c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        }
199217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
1993c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn        @Override
1994ac85f90466dd60d2af8ffc3942d503a0de606726Alan Viverette        public @Config int getChangingConfigurations() {
1995e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mChangingConfigurations
1996e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0)
1997e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0)
1998e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20015f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setShape(@Shape int shape) {
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShape = shape;
2003e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20065f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientType(@GradientType int gradient) {
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradient = gradient;
20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setGradientCenter(float x, float y) {
20119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterX = x;
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCenterY = y;
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20155f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientColors(@Nullable int[] colors) {
2016e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = colors;
2017e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = null;
2018e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
20198bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy        }
2020519494e207322581075c8ea884fde9d33bb9209eAlan Viverette
20215f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setSolidColors(@Nullable ColorStateList colors) {
2022e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mGradientColors = null;
2023e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mSolidColors = colors;
2024e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
2025e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
2026e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
2027e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        private void computeOpacity() {
2028c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = false;
2029c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = false;
203039824f685c33f8aabbe9526b4cc79b7411e8b37fRaph Levien
2031e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors != null) {
2032e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                for (int i = 0; i < mGradientColors.length; i++) {
2033e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    if (!isOpaque(mGradientColors[i])) {
2034e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                        return;
2035e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                    }
2036e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy                }
2037e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            }
2038e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
203922cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            // An unfilled shape is not opaque over bounds or shape
2040e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (mGradientColors == null && mSolidColors == null) {
204122cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase                return;
204222cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase            }
204322cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase
2044c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // Colors are opaque, so opaqueOverShape=true,
2045c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverShape = true;
2046c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            // and opaqueOverBounds=true if shape fills bounds
2047c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik            mOpaqueOverBounds = mShape == RECTANGLE
2048c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadius <= 0
2049c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik                    && mRadiusArray == null;
2050e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy        }
2051e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20525f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setStroke(int width, @Nullable ColorStateList colors, float dashWidth,
20535f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette                float dashGap) {
2054a211dd28b93473c452d68432c602d5209b01c178Alan Viverette            mStrokeWidth = width;
2055e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            mStrokeColors = colors;
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashWidth = dashWidth;
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokeDashGap = dashGap;
2058e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy            computeOpacity();
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadius(float radius) {
20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radius < 0) {
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                radius = 0;
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadius = radius;
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = null;
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2068e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setCornerRadii(float[] radii) {
20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRadiusArray = radii;
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (radii == null) {
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mRadius = 0;
20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2075e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void setSize(int width, int height) {
20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWidth = width;
20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHeight = height;
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20815f63721a6c2c29e639d8d239834a825c535c034aAlan Viverette        public void setGradientRadius(float gradientRadius, @RadiusType int type) {
20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGradientRadius = gradientRadius;
2083b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette            mGradientRadiusType = type;
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2087888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    static boolean isOpaque(int color) {
2088888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette        return ((color >> 24) & 0xff) == 0xff;
2089888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette    }
2090888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette
209152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette    /**
209252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * Creates a new themed GradientDrawable based on the specified constant state.
209352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * <p>
209452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * The resulting drawable is guaranteed to have a new constant state.
209552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     *
209652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     * @param state Constant state from which the drawable inherits
209752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette     */
2098ce52037e0ae0c380f5b834fb3dad105bfaf5e374Alan Viverette    private GradientDrawable(@NonNull GradientState state, @Nullable Resources res) {
209917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        mGradientState = state;
210052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette
210145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        updateLocalState(res);
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
210445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette    private void updateLocalState(Resources res) {
210545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        final GradientState state = mGradientState;
210645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
2107e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        if (state.mSolidColors != null) {
2108519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            final int[] currentState = getState();
2109e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            final int stateColor = state.mSolidColors.getColorForState(currentState, 0);
2110519494e207322581075c8ea884fde9d33bb9209eAlan Viverette            mFillPaint.setColor(stateColor);
2111e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        } else if (state.mGradientColors == null) {
2112cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // If we don't have a solid color and we don't have a gradient,
2113cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // the app is stroking the shape, set the color to the default
2114cf8675ee176a375f873792684d38a47f78348dffRomain Guy            // value of state.mSolidColor
2115cf8675ee176a375f873792684d38a47f78348dffRomain Guy            mFillPaint.setColor(0);
21164d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette        } else {
21174d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            // Otherwise, make sure the fill alpha is maxed out.
21184d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette            mFillPaint.setColor(Color.BLACK);
21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
212017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPadding = state.mPadding;
212217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state.mStrokeWidth >= 0) {
21246a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik            mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStyle(Paint.Style.STROKE);
21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStrokePaint.setStrokeWidth(state.mStrokeWidth);
212717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette
2128e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            if (state.mStrokeColors != null) {
2129083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                final int[] currentState = getState();
2130e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                final int strokeStateColor = state.mStrokeColors.getColorForState(
2131083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                        currentState, 0);
2132083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette                mStrokePaint.setColor(strokeStateColor);
2133083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette            }
21349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (state.mStrokeDashWidth != 0.0f) {
213617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette                final DashPathEffect e = new DashPathEffect(
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0);
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStrokePaint.setPathEffect(e);
21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21413ad771b384b55bc0b9ee9519f457ea7093bb0b74Alan Viverette
2142daec594370f0e47bf07d0c9c968e3c5dfedf0bb5Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
214345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mGradientIsDirty = true;
214445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
214545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        state.computeOpacity();
21469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2148