19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics.drawable; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1980756e38882720860db52f1fcc21fa1505a02abfTor Norbyeimport android.annotation.ColorInt; 20519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.content.res.ColorStateList; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 2352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport android.content.res.Resources.Theme; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 254d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viveretteimport android.graphics.Color; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.ColorFilter; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.DashPathEffect; 2887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.LinearGradient; 30b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craikimport android.graphics.Outline; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Paint; 32519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.Path; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.PixelFormat; 3443027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuff; 3543027b7bca554818cc4223389747d661819d5706Alan Viveretteimport android.graphics.PorterDuffColorFilter; 36519494e207322581075c8ea884fde9d33bb9209eAlan Viveretteimport android.graphics.RadialGradient; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.RectF; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Shader; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.SweepGradient; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viveretteimport com.android.internal.R; 4652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 5317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * A Drawable with a color gradient for buttons, backgrounds, etc. 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 55dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * <p>It can be defined in an XML file with the <code><shape></code> element. For more 56dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * information, see the guide to <a 57dfe5c204403bc56c29bb36410574eab8b1950417Scott Main * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p> 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_visible 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_shape 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_innerRadius 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thicknessRatio 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_thickness 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawable_useLevel 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_width 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSize_height 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_startColor 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerColor 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_endColor 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_useLevel 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_angle 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_type 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerX 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_centerY 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableGradient_gradientRadius 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableSolid_color 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_width 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_color 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashWidth 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawableStroke_dashGap 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_left 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_top 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_right 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GradientDrawablePadding_bottom 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GradientDrawable extends Drawable { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shape is a rectangle, possibly with rounded corners 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int RECTANGLE = 0; 9217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shape is an ellipse 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette public static final int OVAL = 1; 9717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shape is a line 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int LINE = 2; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shape is a ring. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int RING = 3; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gradient is linear (default.) 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int LINEAR_GRADIENT = 0; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gradient is circular. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int RADIAL_GRADIENT = 1; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gradient is a sweep. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int SWEEP_GRADIENT = 2; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 123b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette /** Radius is in pixels. */ 124b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette private static final int RADIUS_TYPE_PIXELS = 0; 125b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 126b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette /** Radius is a fraction of the base size. */ 127b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette private static final int RADIUS_TYPE_FRACTION = 1; 128b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 129b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette /** Radius is a fraction of the bounds size. */ 130b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette private static final int RADIUS_TYPE_FRACTION_PARENT = 2; 131b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 13252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private static final float DEFAULT_INNER_RADIUS_RATIO = 3.0f; 13352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private static final float DEFAULT_THICKNESS_RATIO = 9.0f; 13452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private GradientState mGradientState; 13617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1376a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Rect mPadding; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Paint mStrokePaint; // optional, set by the caller 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ColorFilter mColorFilter; // optional, set by the caller 14143027b7bca554818cc4223389747d661819d5706Alan Viverette private PorterDuffColorFilter mTintFilter; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mAlpha = 0xFF; // modified by the caller 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Path mPath = new Path(); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final RectF mRect = new RectF(); 146e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Paint mLayerPaint; // internal, used if we use saveLayer() 14845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette private boolean mGradientIsDirty; 149684385ddde2ac0c26de0862390ad713aff3fb149Romain Guy private boolean mMutated; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Path mRingPath; 1511041aded2df45094c36831028245fb7c5e9b67b7Romain Guy private boolean mPathIsDirty = true; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1533aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase /** Current gradient radius, valid when {@link #mGradientIsDirty} is false. */ 154861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette private float mGradientRadius; 155861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Controls how the gradient is oriented relative to the drawable's bounds 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public enum Orientation { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the top to the bottom */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TOP_BOTTOM, 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the top-right to the bottom-left */ 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TR_BL, 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the right to the left */ 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RIGHT_LEFT, 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the bottom-right to the top-left */ 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BR_TL, 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the bottom to the top */ 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BOTTOM_TOP, 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the bottom-left to the top-right */ 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BL_TR, 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the left to the right */ 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LEFT_RIGHT, 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** draw the gradient from the top-left to the bottom-right */ 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TL_BR, 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GradientDrawable() { 17945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette this(new GradientState(Orientation.TOP_BOTTOM, null), null); 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new gradient drawable given an orientation and an array 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of colors for the gradient. 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18680756e38882720860db52f1fcc21fa1505a02abfTor Norbye public GradientDrawable(Orientation orientation, @ColorInt int[] colors) { 18745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette this(new GradientState(orientation, colors), null); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getPadding(Rect padding) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPadding != null) { 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project padding.set(mPadding); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getPadding(padding); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Specify radii for each of the 4 corners. For each corner, the array 2028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * contains 2 values, <code>[X_radius, Y_radius]</code>. The corners are ordered 2038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * top-left, top-right, bottom-right, bottom-left. This property 2048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * is honored only when the shape is of type {@link #RECTANGLE}.</p> 2058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 2068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 2078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 2088bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2098bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param radii 4 pairs of X and Y radius for each corner, specified in pixels. 2108bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * The length of this array must be >= 8 2118bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2128bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 2138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #setCornerRadii(float[]) 2148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #setShape(int) 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCornerRadii(float[] radii) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.setCornerRadii(radii); 2181041aded2df45094c36831028245fb7c5e9b67b7Romain Guy mPathIsDirty = true; 2199891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2238bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Specify radius for the corners of the gradient. If this is > 0, then the 2248bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * drawable is drawn in a round-rectangle, rather than a rectangle. This property 2258bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * is honored only when the shape is of type {@link #RECTANGLE}.</p> 2268bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 2278bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 2288bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 2298bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2308bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param radius The radius in pixels of the corners of the rectangle shape 2318bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 2338bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #setCornerRadii(float[]) 23417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setShape(int) 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCornerRadius(float radius) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.setCornerRadius(radius); 2381041aded2df45094c36831028245fb7c5e9b67b7Romain Guy mPathIsDirty = true; 2399891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2418bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Set the stroke width and color for the drawable. If width is zero, 2448bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * then no stroke is drawn.</p> 2458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 2468bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 2478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 2488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param width The width in pixels of the stroke 2508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param color The color of the stroke 2518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 25317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setStroke(int, int, float, float) 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25580756e38882720860db52f1fcc21fa1505a02abfTor Norbye public void setStroke(int width, @ColorInt int color) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setStroke(width, color, 0, 0); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2588bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 2598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 260a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * <p>Set the stroke width and color state list for the drawable. If width 261a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * is zero, then no stroke is drawn.</p> 262a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * <p><strong>Note</strong>: changing this property will affect all instances 263a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * of a drawable loaded from a resource. It is recommended to invoke 264a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * {@link #mutate()} before changing this property.</p> 265a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * 266a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param width The width in pixels of the stroke 267a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param colorStateList The color state list of the stroke 268a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * 269a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @see #mutate() 270a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @see #setStroke(int, ColorStateList, float, float) 271a211dd28b93473c452d68432c602d5209b01c178Alan Viverette */ 272a211dd28b93473c452d68432c602d5209b01c178Alan Viverette public void setStroke(int width, ColorStateList colorStateList) { 273a211dd28b93473c452d68432c602d5209b01c178Alan Viverette setStroke(width, colorStateList, 0, 0); 274a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 275a211dd28b93473c452d68432c602d5209b01c178Alan Viverette 276a211dd28b93473c452d68432c602d5209b01c178Alan Viverette /** 2778bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Set the stroke width and color for the drawable. If width is zero, 2788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * then no stroke is drawn. This method can also be used to dash the stroke.</p> 2798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 2808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 2818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 2828bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param width The width in pixels of the stroke 2848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param color The color of the stroke 28517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes 2868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param dashGap The gap in pixels between dashes 2878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 2888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 28917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setStroke(int, int) 2908bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 29180756e38882720860db52f1fcc21fa1505a02abfTor Norbye public void setStroke(int width, @ColorInt int color, float dashWidth, float dashGap) { 29240df78153987409dbf299b84da9784b69029e184Alan Viverette mGradientState.setStroke(width, ColorStateList.valueOf(color), dashWidth, dashGap); 293a211dd28b93473c452d68432c602d5209b01c178Alan Viverette setStrokeInternal(width, color, dashWidth, dashGap); 294a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 296a211dd28b93473c452d68432c602d5209b01c178Alan Viverette /** 297a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * <p>Set the stroke width and color state list for the drawable. If width 298a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * is zero, then no stroke is drawn. This method can also be used to dash 299a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * the stroke.</p> 300a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * <p><strong>Note</strong>: changing this property will affect all instances 301a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * of a drawable loaded from a resource. It is recommended to invoke 302a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * {@link #mutate()} before changing this property.</p> 303a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * 304a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param width The width in pixels of the stroke 305a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param colorStateList The color state list of the stroke 306a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param dashWidth The length in pixels of the dashes, set to 0 to disable dashes 307a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @param dashGap The gap in pixels between dashes 308a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * 309a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @see #mutate() 310a211dd28b93473c452d68432c602d5209b01c178Alan Viverette * @see #setStroke(int, ColorStateList) 311a211dd28b93473c452d68432c602d5209b01c178Alan Viverette */ 312a211dd28b93473c452d68432c602d5209b01c178Alan Viverette public void setStroke( 313a211dd28b93473c452d68432c602d5209b01c178Alan Viverette int width, ColorStateList colorStateList, float dashWidth, float dashGap) { 31440df78153987409dbf299b84da9784b69029e184Alan Viverette mGradientState.setStroke(width, colorStateList, dashWidth, dashGap); 31540df78153987409dbf299b84da9784b69029e184Alan Viverette final int color; 3167c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette if (colorStateList == null) { 31740df78153987409dbf299b84da9784b69029e184Alan Viverette color = Color.TRANSPARENT; 3187c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette } else { 3197c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette final int[] stateSet = getState(); 32040df78153987409dbf299b84da9784b69029e184Alan Viverette color = colorStateList.getColorForState(stateSet, 0); 3217c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette } 32240df78153987409dbf299b84da9784b69029e184Alan Viverette setStrokeInternal(width, color, dashWidth, dashGap); 323a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 324a211dd28b93473c452d68432c602d5209b01c178Alan Viverette 325a211dd28b93473c452d68432c602d5209b01c178Alan Viverette private void setStrokeInternal(int width, int color, float dashWidth, float dashGap) { 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStrokePaint == null) { 3276a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setStyle(Paint.Style.STROKE); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setStrokeWidth(width); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setColor(color); 33217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DashPathEffect e = null; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dashWidth > 0) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0); 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setPathEffect(e); 3389891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3408bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 3418bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 3428bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 3438bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Sets the size of the shape drawn by this drawable.</p> 3448bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 3458bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 3468bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 3478bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param width The width of the shape used by this drawable 3498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param height The height of the shape used by this drawable 3508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 3528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #setGradientType(int) 3538bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSize(int width, int height) { 3551041aded2df45094c36831028245fb7c5e9b67b7Romain Guy mGradientState.setSize(width, height); 3561041aded2df45094c36831028245fb7c5e9b67b7Romain Guy mPathIsDirty = true; 3579891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 3608bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 3618bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Sets the type of shape used to draw the gradient.</p> 3628bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 3638bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 3648bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 3658bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3668bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param shape The desired shape for this drawable: {@link #LINE}, 3678bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #OVAL}, {@link #RECTANGLE} or {@link #RING} 3688bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3698bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 3708bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setShape(int shape) { 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRingPath = null; 3731041aded2df45094c36831028245fb7c5e9b67b7Romain Guy mPathIsDirty = true; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.setShape(shape); 3759891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 3798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Sets the type of gradient used by this drawable..</p> 3808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 3818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 3828bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 3838bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param gradient The type of the gradient: {@link #LINEAR_GRADIENT}, 3858bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #RADIAL_GRADIENT} or {@link #SWEEP_GRADIENT} 3868bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 3878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 3888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGradientType(int gradient) { 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.setGradientType(gradient); 3913aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 3929891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3958bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 39617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * <p>Sets the center location of the gradient. The radius is honored only when 3978bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * the gradient type is set to {@link #RADIAL_GRADIENT} or {@link #SWEEP_GRADIENT}.</p> 3988bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 3998bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 4008bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 4018bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 4028bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param x The x coordinate of the gradient's center 4038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param y The y coordinate of the gradient's center 4048bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 4058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 4068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #setGradientType(int) 4078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGradientCenter(float x, float y) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.setGradientCenter(x, y); 4103aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 4119891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 4158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Sets the radius of the gradient. The radius is honored only when the 4168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * gradient type is set to {@link #RADIAL_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 gradientRadius The radius of the gradient in pixels 4228bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 4238bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 42417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setGradientType(int) 4258bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGradientRadius(float gradientRadius) { 427861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette mGradientState.setGradientRadius(gradientRadius, TypedValue.COMPLEX_UNIT_PX); 4283aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 4299891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4328bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 433861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette * Returns the radius of the gradient in pixels. The radius is valid only 434861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette * when the gradient type is set to {@link #RADIAL_GRADIENT}. 435861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette * 436861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette * @return Radius in pixels. 437861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette */ 438861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette public float getGradientRadius() { 439861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette if (mGradientState.mGradient != RADIAL_GRADIENT) { 440861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette return 0; 441861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette } 442861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette 443861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette ensureValidRect(); 444861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette return mGradientRadius; 445861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette } 446861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette 447861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette /** 4488bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Sets whether or not this drawable will honor its <code>level</code> 4498bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * property.</p> 4508bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing this property will affect all instances 4518bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 4528bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing this property.</p> 4538bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 4548bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param useLevel True if this drawable should honor its level, false otherwise 4558bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 4568bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 45717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setLevel(int) 45817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #getLevel() 4598bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setUseLevel(boolean useLevel) { 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState.mUseLevel = useLevel; 4623aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 4639891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 46517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int modulateAlpha(int alpha) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int scale = mAlpha + (mAlpha >> 7); 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return alpha * scale >> 8; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4718bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 4728bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * Returns the orientation of the gradient defined in this drawable. 4738bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 4748bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy public Orientation getOrientation() { 4758bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy return mGradientState.mOrientation; 4768bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy } 4778bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 4788bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 4798bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p>Changes the orientation of the gradient defined in this drawable.</p> 4808bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * <p><strong>Note</strong>: changing orientation will affect all instances 4818bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 4828bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * {@link #mutate()} before changing the orientation.</p> 48317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * 4848bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param orientation The desired orientation (angle) of the gradient 48517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * 48617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #mutate() 4878bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 4888bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy public void setOrientation(Orientation orientation) { 4898bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy mGradientState.mOrientation = orientation; 4903aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 4918bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy invalidateSelf(); 4928bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy } 4938bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 4948bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 495e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * Sets the colors used to draw the gradient. 496e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * <p> 497e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * Each color is specified as an ARGB integer and the array must contain at 498e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * least 2 colors. 499e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * <p> 500e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * <strong>Note</strong>: changing colors will affect all instances of a 501e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * drawable loaded from a resource. It is recommended to invoke 502e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * {@link #mutate()} before changing the colors. 5038bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 504e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette * @param colors an array containing 2 or more ARGB colors 5058bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 50617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setColor(int) 5078bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 50880756e38882720860db52f1fcc21fa1505a02abfTor Norbye public void setColors(@ColorInt int[] colors) { 509e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientState.setGradientColors(colors); 5103aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 5118bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy invalidateSelf(); 5128bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy } 5138bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 51516f1d81d47beb1e04504a76de66e2919dde08c33Alan Viverette public void draw(Canvas canvas) { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!ensureValidRect()) { 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // nothing to draw 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // remember the alpha values, in case we temporarily overwrite them 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // when we modulate them with mAlpha 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int prevFillAlpha = mFillPaint.getAlpha(); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int prevStrokeAlpha = mStrokePaint != null ? mStrokePaint.getAlpha() : 0; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // compute the modulate alpha values 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int currFillAlpha = modulateAlpha(prevFillAlpha); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint != null && 530e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy mStrokePaint.getStrokeWidth() > 0; 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean haveFill = currFillAlpha > 0; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final GradientState st = mGradientState; 53343027b7bca554818cc4223389747d661819d5706Alan Viverette final ColorFilter colorFilter = mColorFilter != null ? mColorFilter : mTintFilter; 53443027b7bca554818cc4223389747d661819d5706Alan Viverette 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* we need a layer iff we're drawing both a fill and stroke, and the 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stroke is non-opaque, and our shapetype actually supports 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fill+stroke. Otherwise we can just draw the stroke (if any) on top 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project of the fill (if any) without worrying about blending artifacts. 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 54043027b7bca554818cc4223389747d661819d5706Alan Viverette final boolean useLayer = haveStroke && haveFill && st.mShape != LINE && 54143027b7bca554818cc4223389747d661819d5706Alan Viverette currStrokeAlpha < 255 && (mAlpha < 255 || colorFilter != null); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Drawing with a layer is slower than direct drawing, but it 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project allows us to apply paint effects like alpha and colorfilter to 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project the result of multiple separate draws. In our case, if the user 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project asks for a non-opaque alpha value (via setAlpha), and we're 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project stroking, then we need to apply the alpha AFTER we've drawn 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project both the fill and the stroke. 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (useLayer) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mLayerPaint == null) { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayerPaint = new Paint(); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 55407c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette mLayerPaint.setDither(st.mDither); 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayerPaint.setAlpha(mAlpha); 55643027b7bca554818cc4223389747d661819d5706Alan Viverette mLayerPaint.setColorFilter(colorFilter); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float rad = mStrokePaint.getStrokeWidth(); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.saveLayer(mRect.left - rad, mRect.top - rad, 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRect.right + rad, mRect.bottom + rad, 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayerPaint, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't perform the filter in our individual paints 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // since the layer will do it for us 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setColorFilter(null); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setColorFilter(null); 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* if we're not using a layer, apply the dither/filter to our 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project individual paints 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setAlpha(currFillAlpha); 57207c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette mFillPaint.setDither(st.mDither); 57343027b7bca554818cc4223389747d661819d5706Alan Viverette mFillPaint.setColorFilter(colorFilter); 574e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (colorFilter != null && st.mSolidColors == null) { 575813680780f365648b39873fa26dfae0123d51aedChet Haase mFillPaint.setColor(mAlpha << 24); 57641c769d9a8858ad20b0a6ed942a1cea19ba59d2dRomain Guy } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setAlpha(currStrokeAlpha); 57907c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette mStrokePaint.setDither(st.mDither); 58043027b7bca554818cc4223389747d661819d5706Alan Viverette mStrokePaint.setColorFilter(colorFilter); 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 583e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (st.mShape) { 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RECTANGLE: 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st.mRadiusArray != null) { 587e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik buildPathIfDirty(); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawPath(mPath, mFillPaint); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawPath(mPath, mStrokePaint); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 59261c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } else if (st.mRadius > 0.0f) { 5934e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed // since the caller is only giving us 1 value, we will force 5944e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed // it to be square if the rect is too small in one dimension 5954e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed // to show it. If we did nothing, Skia would clamp the rad 59661c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy // independently along each axis, giving us a thin ellipse 5974e03999ca20fd326e4ded3d7444ddd5c14f369c7Mike Reed // if the rect were very wide but not very tall 598b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik float rad = Math.min(st.mRadius, 599b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik Math.min(mRect.width(), mRect.height()) * 0.5f); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawRoundRect(mRect, rad, rad, mFillPaint); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 60461c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } else { 60543027b7bca554818cc4223389747d661819d5706Alan Viverette if (mFillPaint.getColor() != 0 || colorFilter != null || 606cf8675ee176a375f873792684d38a47f78348dffRomain Guy mFillPaint.getShader() != null) { 607cf8675ee176a375f873792684d38a47f78348dffRomain Guy canvas.drawRect(mRect, mFillPaint); 608cf8675ee176a375f873792684d38a47f78348dffRomain Guy } 60961c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy if (haveStroke) { 61061c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy canvas.drawRect(mRect, mStrokePaint); 61161c8c9c5b2006d18e9310b6521c65b36ffe75ce4Romain Guy } 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case OVAL: 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawOval(mRect, mFillPaint); 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawOval(mRect, mStrokePaint); 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LINE: { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RectF r = mRect; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float y = r.centerY(); 62371b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette if (haveStroke) { 62471b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette canvas.drawLine(r.left, y, r.right, y, mStrokePaint); 62571b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RING: 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Path path = buildRing(st); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawPath(path, mFillPaint); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.drawPath(path, mStrokePaint); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 63617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (useLayer) { 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restore(); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setAlpha(prevFillAlpha); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (haveStroke) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setAlpha(prevStrokeAlpha); 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 646e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik 647e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik private void buildPathIfDirty() { 648e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik final GradientState st = mGradientState; 6493aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase if (mPathIsDirty) { 6503aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase ensureValidRect(); 651e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik mPath.reset(); 652e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW); 6533aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mPathIsDirty = false; 654e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik } 655e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik } 656e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Path buildRing(GradientState st) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPathIsDirty = false; 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f; 66217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RectF bounds = new RectF(mRect); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x = bounds.width() / 2.0f; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float y = bounds.height() / 2.0f; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float thickness = st.mThickness != -1 ? 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st.mThickness : bounds.width() / st.mThicknessRatio; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // inner radius 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float radius = st.mInnerRadius != -1 ? 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st.mInnerRadius : bounds.width() / st.mInnerRadiusRatio; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project RectF innerBounds = new RectF(bounds); 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project innerBounds.inset(x - radius, y - radius); 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds = new RectF(innerBounds); 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.inset(-thickness, -thickness); 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRingPath == null) { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRingPath = new Path(); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 683b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik mRingPath.reset(); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Path ringPath = mRingPath; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // arcTo treats the sweep angle mod 360, so check for that, since we 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // think 360 means draw the entire oval 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sweep < 360 && sweep > -360) { 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.setFillType(Path.FillType.EVEN_ODD); 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // inner top 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.moveTo(x + radius, y); 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // outer top 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.lineTo(x + radius + thickness, y); 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // outer arc 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.arcTo(bounds, 0.0f, sweep, false); 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // inner arc 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.arcTo(innerBounds, sweep, -sweep, false); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.close(); 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // add the entire ovals 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.addOval(bounds, Path.Direction.CW); 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ringPath.addOval(innerBounds, Path.Direction.CCW); 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ringPath; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7098bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy /** 710519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * <p>Changes this drawable to use a single color instead of a gradient.</p> 711e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy * <p><strong>Note</strong>: changing color will affect all instances 7128bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * of a drawable loaded from a resource. It is recommended to invoke 713e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy * {@link #mutate()} before changing the color.</p> 7148bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 7158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @param argb The color used to fill the shape 7168bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * 7178bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy * @see #mutate() 71817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette * @see #setColors(int[]) 7198bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy */ 72080756e38882720860db52f1fcc21fa1505a02abfTor Norbye public void setColor(@ColorInt int argb) { 721e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientState.setSolidColors(ColorStateList.valueOf(argb)); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setColor(argb); 7239891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 726519494e207322581075c8ea884fde9d33bb9209eAlan Viverette /** 727519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * Changes this drawable to use a single color state list instead of a 7287c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette * gradient. Calling this method with a null argument will clear the color 7297c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette * and is equivalent to calling {@link #setColor(int)} with the argument 7307c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette * {@link Color#TRANSPARENT}. 731519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * <p> 732519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * <strong>Note</strong>: changing color will affect all instances of a 733519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * drawable loaded from a resource. It is recommended to invoke 734519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * {@link #mutate()} before changing the color.</p> 735519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * 736519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * @param colorStateList The color state list used to fill the shape 737519494e207322581075c8ea884fde9d33bb9209eAlan Viverette * @see #mutate() 738519494e207322581075c8ea884fde9d33bb9209eAlan Viverette */ 739519494e207322581075c8ea884fde9d33bb9209eAlan Viverette public void setColor(ColorStateList colorStateList) { 740e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientState.setSolidColors(colorStateList); 74140df78153987409dbf299b84da9784b69029e184Alan Viverette final int color; 7427c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette if (colorStateList == null) { 74340df78153987409dbf299b84da9784b69029e184Alan Viverette color = Color.TRANSPARENT; 7447c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette } else { 74540df78153987409dbf299b84da9784b69029e184Alan Viverette final int[] stateSet = getState(); 74640df78153987409dbf299b84da9784b69029e184Alan Viverette color = colorStateList.getColorForState(stateSet, 0); 7477c263c6ee7433d425aa5f69e7eaeeade027dec2fAlan Viverette } 74840df78153987409dbf299b84da9784b69029e184Alan Viverette mFillPaint.setColor(color); 74940df78153987409dbf299b84da9784b69029e184Alan Viverette invalidateSelf(); 750519494e207322581075c8ea884fde9d33bb9209eAlan Viverette } 751519494e207322581075c8ea884fde9d33bb9209eAlan Viverette 752519494e207322581075c8ea884fde9d33bb9209eAlan Viverette @Override 75312b97f5d2b15194ed6673c9838b13c8312157709Alan Viverette protected boolean onStateChange(int[] stateSet) { 754a211dd28b93473c452d68432c602d5209b01c178Alan Viverette boolean invalidateSelf = false; 755a211dd28b93473c452d68432c602d5209b01c178Alan Viverette 756a211dd28b93473c452d68432c602d5209b01c178Alan Viverette final GradientState s = mGradientState; 757e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final ColorStateList solidColors = s.mSolidColors; 758e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (solidColors != null) { 759e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int newColor = solidColors.getColorForState(stateSet, 0); 760519494e207322581075c8ea884fde9d33bb9209eAlan Viverette final int oldColor = mFillPaint.getColor(); 761519494e207322581075c8ea884fde9d33bb9209eAlan Viverette if (oldColor != newColor) { 762519494e207322581075c8ea884fde9d33bb9209eAlan Viverette mFillPaint.setColor(newColor); 763616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette invalidateSelf = true; 764a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 765a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 766a211dd28b93473c452d68432c602d5209b01c178Alan Viverette 767616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette final Paint strokePaint = mStrokePaint; 768616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette if (strokePaint != null) { 769e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final ColorStateList strokeColors = s.mStrokeColors; 770e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (strokeColors != null) { 771e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int newColor = strokeColors.getColorForState(stateSet, 0); 772e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int oldColor = strokePaint.getColor(); 773e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (oldColor != newColor) { 774e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette strokePaint.setColor(newColor); 775616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette invalidateSelf = true; 776616dd4780fb515c596f2764f7e35a30401f7b063Alan Viverette } 777519494e207322581075c8ea884fde9d33bb9209eAlan Viverette } 778519494e207322581075c8ea884fde9d33bb9209eAlan Viverette } 779519494e207322581075c8ea884fde9d33bb9209eAlan Viverette 78043027b7bca554818cc4223389747d661819d5706Alan Viverette if (s.mTint != null && s.mTintMode != null) { 78143027b7bca554818cc4223389747d661819d5706Alan Viverette mTintFilter = updateTintFilter(mTintFilter, s.mTint, s.mTintMode); 78243027b7bca554818cc4223389747d661819d5706Alan Viverette invalidateSelf = true; 78343027b7bca554818cc4223389747d661819d5706Alan Viverette } 78443027b7bca554818cc4223389747d661819d5706Alan Viverette 785a211dd28b93473c452d68432c602d5209b01c178Alan Viverette if (invalidateSelf) { 786a211dd28b93473c452d68432c602d5209b01c178Alan Viverette invalidateSelf(); 787a211dd28b93473c452d68432c602d5209b01c178Alan Viverette return true; 788a211dd28b93473c452d68432c602d5209b01c178Alan Viverette } 789a211dd28b93473c452d68432c602d5209b01c178Alan Viverette 790a211dd28b93473c452d68432c602d5209b01c178Alan Viverette return false; 791519494e207322581075c8ea884fde9d33bb9209eAlan Viverette } 792519494e207322581075c8ea884fde9d33bb9209eAlan Viverette 793519494e207322581075c8ea884fde9d33bb9209eAlan Viverette @Override 794519494e207322581075c8ea884fde9d33bb9209eAlan Viverette public boolean isStateful() { 795a211dd28b93473c452d68432c602d5209b01c178Alan Viverette final GradientState s = mGradientState; 796a211dd28b93473c452d68432c602d5209b01c178Alan Viverette return super.isStateful() 797e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette || (s.mSolidColors != null && s.mSolidColors.isStateful()) 798e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette || (s.mStrokeColors != null && s.mStrokeColors.isStateful()) 79943027b7bca554818cc4223389747d661819d5706Alan Viverette || (s.mTint != null && s.mTint.isStateful()); 800519494e207322581075c8ea884fde9d33bb9209eAlan Viverette } 801519494e207322581075c8ea884fde9d33bb9209eAlan Viverette 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 804e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette return super.getChangingConfigurations() | mGradientState.getChangingConfigurations(); 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8068bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAlpha(int alpha) { 8099891e1fce5f29d0421d34aa481037417bd70853dChet Haase if (alpha != mAlpha) { 8109891e1fce5f29d0421d34aa481037417bd70853dChet Haase mAlpha = alpha; 8119891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 8129891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 816b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase public int getAlpha() { 817b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase return mAlpha; 818b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase } 819b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase 820b1af7f3d4be6cd6bc6e1e805f22c209e19bf928fChet Haase @Override 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDither(boolean dither) { 82207c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette if (dither != mGradientState.mDither) { 82307c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette mGradientState.mDither = dither; 8249891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 8259891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 82938b5f597de96cd892add9017dc810212f549bf68John Spurlock public ColorFilter getColorFilter() { 83038b5f597de96cd892add9017dc810212f549bf68John Spurlock return mColorFilter; 83138b5f597de96cd892add9017dc810212f549bf68John Spurlock } 83238b5f597de96cd892add9017dc810212f549bf68John Spurlock 83338b5f597de96cd892add9017dc810212f549bf68John Spurlock @Override 834bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik public void setColorFilter(ColorFilter colorFilter) { 835bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik if (colorFilter != mColorFilter) { 836bd3bfc5285dcacff0a69fecf3baeeeb90d887a58Chris Craik mColorFilter = colorFilter; 8379891e1fce5f29d0421d34aa481037417bd70853dChet Haase invalidateSelf(); 8389891e1fce5f29d0421d34aa481037417bd70853dChet Haase } 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 84243027b7bca554818cc4223389747d661819d5706Alan Viverette public void setTintList(ColorStateList tint) { 84343027b7bca554818cc4223389747d661819d5706Alan Viverette mGradientState.mTint = tint; 84443027b7bca554818cc4223389747d661819d5706Alan Viverette mTintFilter = updateTintFilter(mTintFilter, tint, mGradientState.mTintMode); 84543027b7bca554818cc4223389747d661819d5706Alan Viverette invalidateSelf(); 84643027b7bca554818cc4223389747d661819d5706Alan Viverette } 84743027b7bca554818cc4223389747d661819d5706Alan Viverette 84843027b7bca554818cc4223389747d661819d5706Alan Viverette @Override 84943027b7bca554818cc4223389747d661819d5706Alan Viverette public void setTintMode(PorterDuff.Mode tintMode) { 85043027b7bca554818cc4223389747d661819d5706Alan Viverette mGradientState.mTintMode = tintMode; 85143027b7bca554818cc4223389747d661819d5706Alan Viverette mTintFilter = updateTintFilter(mTintFilter, mGradientState.mTint, tintMode); 85243027b7bca554818cc4223389747d661819d5706Alan Viverette invalidateSelf(); 85343027b7bca554818cc4223389747d661819d5706Alan Viverette } 85443027b7bca554818cc4223389747d661819d5706Alan Viverette 85543027b7bca554818cc4223389747d661819d5706Alan Viverette @Override 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getOpacity() { 857888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette return (mAlpha == 255 && mGradientState.mOpaqueOverBounds && isOpaqueForState()) ? 8580a1c6f021be032f5aecb341c2794efb06c0a8a0dAlan Viverette PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT; 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onBoundsChange(Rect r) { 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onBoundsChange(r); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRingPath = null; 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPathIsDirty = true; 8663aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean onLevelChange(int level) { 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onLevelChange(level); 8723aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = true; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPathIsDirty = true; 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidateSelf(); 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8793aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase * This checks mGradientIsDirty, and if it is true, recomputes both our drawing 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * rectangle (mRect) and the gradient itself, since it depends on our 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * rectangle too. 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the resulting rectangle is not empty, false otherwise 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean ensureValidRect() { 8853aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase if (mGradientIsDirty) { 8863aff2a0813ad77fd41b39b6a636faf2de6d78accChet Haase mGradientIsDirty = false; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect bounds = getBounds(); 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float inset = 0; 89017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStrokePaint != null) { 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project inset = mStrokePaint.getStrokeWidth() * 0.5f; 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final GradientState st = mGradientState; 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRect.set(bounds.left + inset, bounds.top + inset, 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.right - inset, bounds.bottom - inset); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 900e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int[] gradientColors = st.mGradientColors; 901e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (gradientColors != null) { 902e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final RectF r = mRect; 903e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final float x0, x1, y0, y1; 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st.mGradient == LINEAR_GRADIENT) { 9067979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (st.mOrientation) { 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case TOP_BOTTOM: 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left; y0 = r.top; 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = x0; y1 = level * r.bottom; 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case TR_BL: 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.right; y0 = r.top; 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.left; y1 = level * r.bottom; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case RIGHT_LEFT: 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.right; y0 = r.top; 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.left; y1 = y0; 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BR_TL: 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.right; y0 = r.bottom; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.left; y1 = level * r.top; 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BOTTOM_TOP: 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left; y0 = r.bottom; 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = x0; y1 = level * r.top; 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case BL_TR: 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left; y0 = r.bottom; 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.right; y1 = level * r.top; 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LEFT_RIGHT: 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left; y0 = r.top; 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.right; y1 = y0; 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default:/* TL_BR */ 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left; y0 = r.top; 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x1 = level * r.right; y1 = level * r.bottom; 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1, 943e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette gradientColors, st.mPositions, Shader.TileMode.CLAMP)); 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (st.mGradient == RADIAL_GRADIENT) { 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left + (r.right - r.left) * st.mCenterX; 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y0 = r.top + (r.bottom - r.top) * st.mCenterY; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 948861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette float radius = st.mGradientRadius; 949b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) { 950b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette // Fall back to parent width or height if intrinsic 951b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette // size is not specified. 952b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette final float width = st.mWidth >= 0 ? st.mWidth : r.width(); 953b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette final float height = st.mHeight >= 0 ? st.mHeight : r.height(); 954b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette radius *= Math.min(width, height); 955b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette } else if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION_PARENT) { 956861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette radius *= Math.min(r.width(), r.height()); 957861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette } 958b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 959861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette if (st.mUseLevel) { 960861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette radius *= getLevel() / 10000.0f; 961861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette } 962b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 963861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette mGradientRadius = radius; 964b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 965b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette if (radius <= 0) { 966b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette // We can't have a shader with non-positive radius, so 967b4f8a981769e95500ab6c86ab45102dc9c7e53c6Alan Viverette // let's have a very, very small radius. 968b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette radius = 0.001f; 969b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette } 970b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette 971861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette mFillPaint.setShader(new RadialGradient( 972e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette x0, y0, radius, gradientColors, null, Shader.TileMode.CLAMP)); 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (st.mGradient == SWEEP_GRADIENT) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x0 = r.left + (r.right - r.left) * st.mCenterX; 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project y0 = r.top + (r.bottom - r.top) * st.mCenterY; 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 977e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette int[] tempColors = gradientColors; 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float[] tempPositions = null; 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st.mUseLevel) { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempColors = st.mTempColors; 982e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int length = gradientColors.length; 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tempColors == null || tempColors.length != length + 1) { 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempColors = st.mTempColors = new int[length + 1]; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 986e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette System.arraycopy(gradientColors, 0, tempColors, 0, length); 987e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette tempColors[length] = gradientColors[length - 1]; 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempPositions = st.mTempPositions; 99052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final float fraction = 1.0f / (length - 1); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tempPositions == null || tempPositions.length != length + 1) { 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempPositions = st.mTempPositions = new float[length + 1]; 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 99552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final float level = getLevel() / 10000.0f; 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < length; i++) { 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempPositions[i] = i * fraction * level; 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tempPositions[length] = 1.0f; 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions)); 10034d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette } 10044d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette 10054d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette // If we don't have a solid color, the alpha channel must be 10064d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette // maxed out so that alpha modulation works correctly. 1007e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (st.mSolidColors == null) { 10084d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette mFillPaint.setColor(Color.BLACK); 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return !mRect.isEmpty(); 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 101652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme) 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throws XmlPullParserException, IOException { 101852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawable); 101952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.inflateWithAttributes(r, parser, a, R.styleable.GradientDrawable_visible); 102017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateStateFromTypedArray(a); 102152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 102252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 102352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette inflateChildElements(r, parser, attrs, theme); 102452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 102545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette updateLocalState(r); 102652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 102752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 102852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 102952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public void applyTheme(Theme t) { 103052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette super.applyTheme(t); 103152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 103252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final GradientState state = mGradientState; 103317cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette if (state == null) { 103417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette return; 103552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 103652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 103717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette if (state.mThemeAttrs != null) { 103817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette final TypedArray a = t.resolveAttributes( 103917cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette state.mThemeAttrs, R.styleable.GradientDrawable); 104017cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette updateStateFromTypedArray(a); 104117cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette a.recycle(); 104217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette } 104352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 104445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette if (state.mTint != null && state.mTint.canApplyTheme()) { 1045e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette state.mTint = state.mTint.obtainForTheme(t); 104645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette } 104745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 1048e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (state.mSolidColors != null && state.mSolidColors.canApplyTheme()) { 1049e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette state.mSolidColors = state.mSolidColors.obtainForTheme(t); 105045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette } 105145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 1052e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (state.mStrokeColors != null && state.mStrokeColors.canApplyTheme()) { 1053e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette state.mStrokeColors = state.mStrokeColors.obtainForTheme(t); 105445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette } 105545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 105617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette applyThemeChildElements(t); 105752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 105845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette updateLocalState(t.getResources()); 105952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 106052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 106152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 106252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * Updates the constant state from the values in the typed array. 106352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 106452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private void updateStateFromTypedArray(TypedArray a) { 106552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final GradientState state = mGradientState; 106652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 10678e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 10688e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 10698e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 107017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette // Extract the theme attributes, if any. 107117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 107252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 107317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette state.mShape = a.getInt(R.styleable.GradientDrawable_shape, state.mShape); 107407c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette state.mDither = a.getBoolean(R.styleable.GradientDrawable_dither, state.mDither); 107552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 107652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (state.mShape == RING) { 107717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette state.mInnerRadius = a.getDimensionPixelSize( 107817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawable_innerRadius, state.mInnerRadius); 107952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 108017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (state.mInnerRadius == -1) { 108152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette state.mInnerRadiusRatio = a.getFloat( 108217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawable_innerRadiusRatio, state.mInnerRadiusRatio); 108352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 108452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 108517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette state.mThickness = a.getDimensionPixelSize( 108617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawable_thickness, state.mThickness); 108752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 108817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (state.mThickness == -1) { 108952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette state.mThicknessRatio = a.getFloat( 109017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawable_thicknessRatio, state.mThicknessRatio); 109152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 109252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 109317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette state.mUseLevelForShape = a.getBoolean( 109417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawable_useLevel, state.mUseLevelForShape); 109552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 109643027b7bca554818cc4223389747d661819d5706Alan Viverette 109743027b7bca554818cc4223389747d661819d5706Alan Viverette final int tintMode = a.getInt(R.styleable.GradientDrawable_tintMode, -1); 109843027b7bca554818cc4223389747d661819d5706Alan Viverette if (tintMode != -1) { 109943027b7bca554818cc4223389747d661819d5706Alan Viverette state.mTintMode = Drawable.parseTintMode(tintMode, PorterDuff.Mode.SRC_IN); 110043027b7bca554818cc4223389747d661819d5706Alan Viverette } 110143027b7bca554818cc4223389747d661819d5706Alan Viverette 110243027b7bca554818cc4223389747d661819d5706Alan Viverette final ColorStateList tint = a.getColorStateList(R.styleable.GradientDrawable_tint); 110343027b7bca554818cc4223389747d661819d5706Alan Viverette if (tint != null) { 110443027b7bca554818cc4223389747d661819d5706Alan Viverette state.mTint = tint; 110543027b7bca554818cc4223389747d661819d5706Alan Viverette } 110687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette 110787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetLeft = a.getDimensionPixelSize( 110887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.GradientDrawable_opticalInsetLeft, state.mOpticalInsets.left); 110987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetTop = a.getDimensionPixelSize( 111087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.GradientDrawable_opticalInsetTop, state.mOpticalInsets.top); 111187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetRight = a.getDimensionPixelSize( 111287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.GradientDrawable_opticalInsetRight, state.mOpticalInsets.right); 111387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetBottom = a.getDimensionPixelSize( 111487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.GradientDrawable_opticalInsetBottom, state.mOpticalInsets.bottom); 111587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette state.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom); 111652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 111752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 111852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 111952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 1120d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme(); 112152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 112252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 112352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private void applyThemeChildElements(Theme t) { 112417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final GradientState st = mGradientState; 112552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 112617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrSize != null) { 112717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 112817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrSize, R.styleable.GradientDrawableSize); 112917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableSize(a); 113052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 113152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 113252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 113317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrGradient != null) { 113417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 113517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrGradient, R.styleable.GradientDrawableGradient); 113617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette try { 113717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableGradient(t.getResources(), a); 113817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette } catch (XmlPullParserException e) { 113917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette throw new RuntimeException(e); 114017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette } finally { 114117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a.recycle(); 114217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette } 114352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 114452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 114517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrSolid != null) { 114617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 114717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrSolid, R.styleable.GradientDrawableSolid); 114817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableSolid(a); 114952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 115052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 115152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 115217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrStroke != null) { 115317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 115417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrStroke, R.styleable.GradientDrawableStroke); 115517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableStroke(a); 115652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 115752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 115852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 115917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrCorners != null) { 116017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 116117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrCorners, R.styleable.DrawableCorners); 116217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateDrawableCorners(a); 116352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 116452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 116552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 116617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (st.mAttrPadding != null) { 116717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedArray a = t.resolveAttributes( 116817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrPadding, R.styleable.GradientDrawablePadding); 116917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawablePadding(a); 117052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.recycle(); 117152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 117252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 117352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 117452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs, 117552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette Theme theme) throws XmlPullParserException, IOException { 117652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette TypedArray a; 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179ed7894352f8addfe3d0da75cc7fe8bc6fef201dcRomain Guy final int innerDepth = parser.getDepth() + 1; 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int depth; 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && ((depth=parser.getDepth()) >= innerDepth 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || type != XmlPullParser.END_TAG)) { 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type != XmlPullParser.START_TAG) { 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (depth > innerDepth) { 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 119152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name = parser.getName(); 119317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (name.equals("size")) { 119517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSize); 119617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableSize(a); 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals("gradient")) { 119917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableGradient); 120017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableGradient(r, a); 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals("solid")) { 120317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableSolid); 120417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableSolid(a); 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals("stroke")) { 120717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawableStroke); 120817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawableStroke(a); 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals("corners")) { 121117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.DrawableCorners); 121217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateDrawableCorners(a); 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (name.equals("padding")) { 121517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a = obtainAttributes(r, theme, attrs, R.styleable.GradientDrawablePadding); 121617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette updateGradientDrawablePadding(a); 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w("drawable", "Bad element under <shape>: " + name); 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 122152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 122252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 122352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 122417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateGradientDrawablePadding(TypedArray a) { 122517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final GradientState st = mGradientState; 122652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 12278e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 12288e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 12298e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 123052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // Extract the theme attributes, if any. 123117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrPadding = a.extractThemeAttrs(); 123217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1233982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette if (st.mPadding == null) { 1234982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette st.mPadding = new Rect(); 1235982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette } 1236982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette 123717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final Rect pad = st.mPadding; 123817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette pad.set(a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_left, pad.left), 123917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_top, pad.top), 124017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_right, pad.right), 124117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a.getDimensionPixelOffset(R.styleable.GradientDrawablePadding_bottom, pad.bottom)); 124217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette mPadding = pad; 124352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 1244e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 124517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateDrawableCorners(TypedArray a) { 124617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final GradientState st = mGradientState; 124717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 12488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 12498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 12508e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 125117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette // Extract the theme attributes, if any. 125217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrCorners = a.extractThemeAttrs(); 125317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 125417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final int radius = a.getDimensionPixelSize( 125517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.DrawableCorners_radius, (int) st.mRadius); 125652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette setCornerRadius(radius); 125717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 125817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette // TODO: Update these to be themeable. 125917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final int topLeftRadius = a.getDimensionPixelSize( 126052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.DrawableCorners_topLeftRadius, radius); 126117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final int topRightRadius = a.getDimensionPixelSize( 126252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.DrawableCorners_topRightRadius, radius); 126317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final int bottomLeftRadius = a.getDimensionPixelSize( 126452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.DrawableCorners_bottomLeftRadius, radius); 126517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final int bottomRightRadius = a.getDimensionPixelSize( 126652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.DrawableCorners_bottomRightRadius, radius); 126752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (topLeftRadius != radius || topRightRadius != radius || 126852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette bottomLeftRadius != radius || bottomRightRadius != radius) { 126952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // The corner radii are specified in clockwise order (see Path.addRoundRect()) 127052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette setCornerRadii(new float[] { 127152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette topLeftRadius, topLeftRadius, 127252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette topRightRadius, topRightRadius, 127352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette bottomRightRadius, bottomRightRadius, 127452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette bottomLeftRadius, bottomLeftRadius 127552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette }); 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 127752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 127852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 127917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateGradientDrawableStroke(TypedArray a) { 128017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final GradientState st = mGradientState; 128117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 12828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 12838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 12848e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 12858e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Extract the theme attributes, if any. 128617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrStroke = a.extractThemeAttrs(); 128717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 12883b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette // We have an explicit stroke defined, so the default stroke width 12893b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette // must be at least 0 or the current stroke width. 12903b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette final int defaultStrokeWidth = Math.max(0, st.mStrokeWidth); 129152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int width = a.getDimensionPixelSize( 12923b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette R.styleable.GradientDrawableStroke_width, defaultStrokeWidth); 129352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final float dashWidth = a.getDimension( 129417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawableStroke_dashWidth, st.mStrokeDashWidth); 129517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 129617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette ColorStateList colorStateList = a.getColorStateList( 129717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawableStroke_color); 129817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (colorStateList == null) { 1299e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette colorStateList = st.mStrokeColors; 130017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette } 130117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 130252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (dashWidth != 0.0f) { 130352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final float dashGap = a.getDimension( 130417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawableStroke_dashGap, st.mStrokeDashGap); 130552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette setStroke(width, colorStateList, dashWidth, dashGap); 130652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else { 130752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette setStroke(width, colorStateList); 130852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 130952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 131052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 131117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateGradientDrawableSolid(TypedArray a) { 13128e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette final GradientState st = mGradientState; 13138e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 13148e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 13158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 13168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 13178e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Extract the theme attributes, if any. 13188e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mAttrSolid = a.extractThemeAttrs(); 131917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 132052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final ColorStateList colorStateList = a.getColorStateList( 132152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.GradientDrawableSolid_color); 132217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette if (colorStateList != null) { 132317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette setColor(colorStateList); 132417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette } 132552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 132652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 132717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateGradientDrawableGradient(Resources r, TypedArray a) 132852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throws XmlPullParserException { 132952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final GradientState st = mGradientState; 133017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 13318e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 13328e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 13338e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 133417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette // Extract the theme attributes, if any. 133517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrGradient = a.extractThemeAttrs(); 133617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 133717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mCenterX = getFloatOrFraction( 133817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a, R.styleable.GradientDrawableGradient_centerX, st.mCenterX); 133917dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mCenterY = getFloatOrFraction( 134017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette a, R.styleable.GradientDrawableGradient_centerY, st.mCenterY); 134117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mUseLevel = a.getBoolean( 134217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawableGradient_useLevel, st.mUseLevel); 134317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mGradient = a.getInt( 134417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette R.styleable.GradientDrawableGradient_type, st.mGradient); 134517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 134617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette // TODO: Update these to be themeable. 134752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int startColor = a.getColor( 134852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.GradientDrawableGradient_startColor, 0); 134952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final boolean hasCenterColor = a.hasValue( 135052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.GradientDrawableGradient_centerColor); 135152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int centerColor = a.getColor( 135252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.GradientDrawableGradient_centerColor, 0); 135352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int endColor = a.getColor( 135452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette R.styleable.GradientDrawableGradient_endColor, 0); 135552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 135652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (hasCenterColor) { 1357e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors = new int[3]; 1358e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors[0] = startColor; 1359e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors[1] = centerColor; 1360e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors[2] = endColor; 136117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 136252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mPositions = new float[3]; 136352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mPositions[0] = 0.0f; 136452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // Since 0.5f is default value, try to take the one that isn't 0.5f 136552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mPositions[1] = st.mCenterX != 0.5f ? st.mCenterX : st.mCenterY; 136652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mPositions[2] = 1f; 136752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else { 1368e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors = new int[2]; 1369e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors[0] = startColor; 1370e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette st.mGradientColors[1] = endColor; 137152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 137252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 137352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (st.mGradient == LINEAR_GRADIENT) { 137417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle); 137552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette angle %= 360; 137652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 137752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (angle % 45 != 0) { 137852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throw new XmlPullParserException(a.getPositionDescription() 137952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette + "<gradient> tag requires 'angle' attribute to " 138052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette + "be a multiple of 45"); 138152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 138252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 138317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAngle = angle; 138417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 138552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette switch (angle) { 138652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 0: 138752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.LEFT_RIGHT; 138852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 138952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 45: 139052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.BL_TR; 139152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 139252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 90: 139352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.BOTTOM_TOP; 139452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 139552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 135: 139652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.BR_TL; 139752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 139852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 180: 139952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.RIGHT_LEFT; 140052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 140152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 225: 140252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.TR_BL; 140352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 140452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 270: 140552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.TOP_BOTTOM; 140652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 140752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette case 315: 140852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mOrientation = Orientation.TL_BR; 140952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette break; 141052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 141152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else { 141217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius); 141352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (tv != null) { 141452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final float radius; 141552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int radiusType; 141652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (tv.type == TypedValue.TYPE_FRACTION) { 141752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette radius = tv.getFraction(1.0f, 1.0f); 141852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 141952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette final int unit = (tv.data >> TypedValue.COMPLEX_UNIT_SHIFT) 142052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette & TypedValue.COMPLEX_UNIT_MASK; 142152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette if (unit == TypedValue.COMPLEX_UNIT_FRACTION_PARENT) { 142252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette radiusType = RADIUS_TYPE_FRACTION_PARENT; 142352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else { 142452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette radiusType = RADIUS_TYPE_FRACTION; 142552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 14262efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette } else if (tv.type == TypedValue.TYPE_DIMENSION) { 142752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette radius = tv.getDimension(r.getDisplayMetrics()); 142852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette radiusType = RADIUS_TYPE_PIXELS; 14292efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette } else { 14302efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette radius = tv.getFloat(); 14312efbe9816e097a07864a04f0722d5669b98699f4Alan Viverette radiusType = RADIUS_TYPE_PIXELS; 143252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 143352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 143452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mGradientRadius = radius; 143552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette st.mGradientRadiusType = radiusType; 143652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } else if (st.mGradient == RADIAL_GRADIENT) { 143752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette throw new XmlPullParserException( 143852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette a.getPositionDescription() 143952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette + "<gradient> tag requires 'gradientRadius' " 144052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette + "attribute with radial type"); 144152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 144252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 144352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 144452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 144517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette private void updateGradientDrawableSize(TypedArray a) { 144617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final GradientState st = mGradientState; 144752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 14488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 14498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette st.mChangingConfigurations |= a.getChangingConfigurations(); 14508e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 145152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette // Extract the theme attributes, if any. 145217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mAttrSize = a.extractThemeAttrs(); 145317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 145417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mWidth = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_width, st.mWidth); 145517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette st.mHeight = a.getDimensionPixelSize(R.styleable.GradientDrawableSize_height, st.mHeight); 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float getFloatOrFraction(TypedArray a, int index, float defaultValue) { 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedValue tv = a.peekValue(index); 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float v = defaultValue; 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tv != null) { 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean vIsFraction = tv.type == TypedValue.TYPE_FRACTION; 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = vIsFraction ? tv.getFraction(1.0f, 1.0f) : tv.getFloat(); 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 146717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicWidth() { 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGradientState.mWidth; 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getIntrinsicHeight() { 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGradientState.mHeight; 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 147717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 147887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette /** @hide */ 147987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette @Override 148087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette public Insets getOpticalInsets() { 148187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette return mGradientState.mOpticalInsets; 148287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette } 148387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ConstantState getConstantState() { 14866efd2bad954e0e5bd74916a32f036a0f149dcd4dChristopher Lais mGradientState.mChangingConfigurations = getChangingConfigurations(); 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mGradientState; 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1490888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette private boolean isOpaqueForState() { 1491888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette if (mGradientState.mStrokeWidth >= 0 && mStrokePaint != null 1492888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette && !isOpaque(mStrokePaint.getColor())) { 1493888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette return false; 1494888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette } 1495888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette 1496888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette if (!isOpaque(mFillPaint.getColor())) { 1497888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette return false; 1498888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette } 1499888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette 1500888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette return true; 1501888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette } 1502888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 150431ba192dd201df2cad96a8c503f730130ab0d80fChris Craik public void getOutline(Outline outline) { 1505b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik final GradientState st = mGradientState; 1506b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik final Rect bounds = getBounds(); 1507c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik // only report non-zero alpha if shape being drawn is opaque 1508888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette outline.setAlpha(st.mOpaqueOverShape && isOpaqueForState() ? (mAlpha / 255.0f) : 0.0f); 1509b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik 1510b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik switch (st.mShape) { 1511b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik case RECTANGLE: 1512b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik if (st.mRadiusArray != null) { 1513e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik buildPathIfDirty(); 1514e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik outline.setConvexPath(mPath); 151531ba192dd201df2cad96a8c503f730130ab0d80fChris Craik return; 1516b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik } 1517e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik 1518b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik float rad = 0; 1519b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik if (st.mRadius > 0.0f) { 1520b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik // clamp the radius based on width & height, matching behavior in draw() 1521b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik rad = Math.min(st.mRadius, 1522b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik Math.min(bounds.width(), bounds.height()) * 0.5f); 1523b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik } 15247979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik outline.setRoundRect(bounds, rad); 152531ba192dd201df2cad96a8c503f730130ab0d80fChris Craik return; 15267979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik case OVAL: 15277979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik outline.setOval(bounds); 152831ba192dd201df2cad96a8c503f730130ab0d80fChris Craik return; 15297979388d4f7d5d9dbfcf7e1cc4709f8088c034aeChris Craik case LINE: 15303b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette // Hairlines (0-width stroke) must have a non-empty outline for 15313b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette // shadows to draw correctly, so we'll use a very small width. 15323b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette final float halfStrokeWidth = mStrokePaint == null ? 15333b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette 0.0001f : mStrokePaint.getStrokeWidth() * 0.5f; 15343b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette final float centerY = bounds.centerY(); 15353b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette final int top = (int) Math.floor(centerY - halfStrokeWidth); 15363b983a74c6bac40aad191dfcfbed930cd25a9a01Alan Viverette final int bottom = (int) Math.ceil(centerY + halfStrokeWidth); 1537b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik 1538e6a39b12656ab8d5c77d8366b24aa6410fd42e11Chris Craik outline.setRect(bounds.left, top, bounds.right, bottom); 153931ba192dd201df2cad96a8c503f730130ab0d80fChris Craik return; 1540b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik default: 154131ba192dd201df2cad96a8c503f730130ab0d80fChris Craik // TODO: support more complex shapes 1542b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik } 1543b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik } 1544b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik 1545b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik @Override 15469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable mutate() { 15479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mMutated && super.mutate() == this) { 15489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientState = new GradientState(mGradientState); 154945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette updateLocalState(null); 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMutated = true; 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 15539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1555727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette /** 1556727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette * @hide 1557727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette */ 1558727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette public void clearMutated() { 1559727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette super.clearMutated(); 1560727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mMutated = false; 1561727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette } 1562727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final static class GradientState extends ConstantState { 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mChangingConfigurations; 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mShape = RECTANGLE; 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mGradient = LINEAR_GRADIENT; 156771b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public int mAngle = 0; 15689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Orientation mOrientation; 1569e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public ColorStateList mSolidColors; 1570e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public ColorStateList mStrokeColors; 1571e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public int[] mGradientColors; 15729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int[] mTempColors; // no need to copy 15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float[] mTempPositions; // no need to copy 15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float[] mPositions; 157571b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public int mStrokeWidth = -1; // if >= 0 use stroking. 157671b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public float mStrokeDashWidth = 0.0f; 157771b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public float mStrokeDashGap = 0.0f; 157871b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public float mRadius = 0.0f; // use this if mRadiusArray is null 157971b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public float[] mRadiusArray = null; 158071b2fbde5601b2347992c4e489d6dfe5f2c777e1Alan Viverette public Rect mPadding = null; 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mWidth = -1; 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int mHeight = -1; 158317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette public float mInnerRadiusRatio = DEFAULT_INNER_RADIUS_RATIO; 158417dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette public float mThicknessRatio = DEFAULT_THICKNESS_RATIO; 158517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette public int mInnerRadius = -1; 158617dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette public int mThickness = -1; 158707c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette public boolean mDither = false; 158887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette public Insets mOpticalInsets = Insets.NONE; 158907c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette 1590969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette float mCenterX = 0.5f; 1591969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette float mCenterY = 0.5f; 1592969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette float mGradientRadius = 0.5f; 1593969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette int mGradientRadiusType = RADIUS_TYPE_PIXELS; 1594969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette boolean mUseLevel = false; 1595969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette boolean mUseLevelForShape = true; 1596969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette 1597969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette boolean mOpaqueOverBounds; 1598969ca91acd008cb33b72888e0b9e7109556db019Alan Viverette boolean mOpaqueOverShape; 15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 160043027b7bca554818cc4223389747d661819d5706Alan Viverette ColorStateList mTint = null; 160143027b7bca554818cc4223389747d661819d5706Alan Viverette PorterDuff.Mode mTintMode = DEFAULT_TINT_MODE; 160243027b7bca554818cc4223389747d661819d5706Alan Viverette 160352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mThemeAttrs; 160452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrSize; 160552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrGradient; 160652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrSolid; 160752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrStroke; 160852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrCorners; 160952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette int[] mAttrPadding; 161052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 1611e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public GradientState(Orientation orientation, int[] gradientColors) { 16129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOrientation = orientation; 1613e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette setGradientColors(gradientColors); 16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GradientState(GradientState state) { 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChangingConfigurations = state.mChangingConfigurations; 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShape = state.mShape; 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradient = state.mGradient; 162017dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette mAngle = state.mAngle; 16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOrientation = state.mOrientation; 1622e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mSolidColors = state.mSolidColors; 1623e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (state.mGradientColors != null) { 1624e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientColors = state.mGradientColors.clone(); 1625562bf17c6c7c5226b2220e27a1543d4a43543d6cPhil Dubach } 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.mPositions != null) { 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPositions = state.mPositions.clone(); 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mStrokeColors = state.mStrokeColors; 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokeWidth = state.mStrokeWidth; 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokeDashWidth = state.mStrokeDashWidth; 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokeDashGap = state.mStrokeDashGap; 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadius = state.mRadius; 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.mRadiusArray != null) { 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadiusArray = state.mRadiusArray.clone(); 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.mPadding != null) { 1638982c59a55f8f11d0e26be93780b292adacd56f49Alan Viverette mPadding = new Rect(state.mPadding); 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = state.mWidth; 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = state.mHeight; 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInnerRadiusRatio = state.mInnerRadiusRatio; 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThicknessRatio = state.mThicknessRatio; 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInnerRadius = state.mInnerRadius; 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThickness = state.mThickness; 164607c661e677b354c2298a2b81f19fd24e5ab1b0e0Alan Viverette mDither = state.mDither; 164787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette mOpticalInsets = state.mOpticalInsets; 16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCenterX = state.mCenterX; 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCenterY = state.mCenterY; 16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientRadius = state.mGradientRadius; 1651b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette mGradientRadiusType = state.mGradientRadiusType; 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUseLevel = state.mUseLevel; 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUseLevelForShape = state.mUseLevelForShape; 1654c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik mOpaqueOverBounds = state.mOpaqueOverBounds; 1655c3a63c1fbb47f167f6736ad637fd6c6e3ee9d1d8Alan Viverette mOpaqueOverShape = state.mOpaqueOverShape; 165643027b7bca554818cc4223389747d661819d5706Alan Viverette mTint = state.mTint; 165743027b7bca554818cc4223389747d661819d5706Alan Viverette mTintMode = state.mTintMode; 165852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mThemeAttrs = state.mThemeAttrs; 165952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrSize = state.mAttrSize; 166052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrGradient = state.mAttrGradient; 166152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrSolid = state.mAttrSolid; 166252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrStroke = state.mAttrStroke; 166352b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrCorners = state.mAttrCorners; 166452b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette mAttrPadding = state.mAttrPadding; 166552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette } 166652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 166752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette @Override 166852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette public boolean canApplyTheme() { 166945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette return mThemeAttrs != null 167045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || mAttrSize != null || mAttrGradient != null 167145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || mAttrSolid != null || mAttrStroke != null 167245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || mAttrCorners != null || mAttrPadding != null 167345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || (mTint != null && mTint.canApplyTheme()) 1674e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette || (mStrokeColors != null && mStrokeColors.canApplyTheme()) 1675e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette || (mSolidColors != null && mSolidColors.canApplyTheme()) 167645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || super.canApplyTheme(); 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable newDrawable() { 168145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette return new GradientDrawable(this, null); 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 168317dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1685c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn public Drawable newDrawable(Resources res) { 168645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette return new GradientDrawable(this, res); 1687c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn } 168817dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1689c2974809373697147cbe5754835cc871fb93aef1Dianne Hackborn @Override 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getChangingConfigurations() { 1691e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette return mChangingConfigurations 1692e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette | (mStrokeColors != null ? mStrokeColors.getChangingConfigurations() : 0) 1693e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette | (mSolidColors != null ? mSolidColors.getChangingConfigurations() : 0) 1694e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette | (mTint != null ? mTint.getChangingConfigurations() : 0); 16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setShape(int shape) { 16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mShape = shape; 1699e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy computeOpacity(); 17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGradientType(int gradient) { 17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradient = gradient; 17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGradientCenter(float x, float y) { 17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCenterX = x; 17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mCenterY = y; 17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1711e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public void setGradientColors(int[] colors) { 1712e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientColors = colors; 1713e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mSolidColors = null; 1714e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy computeOpacity(); 17158bd9698b66d2e1219931ca1be5f81efaba3ed95aRomain Guy } 1716519494e207322581075c8ea884fde9d33bb9209eAlan Viverette 1717e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public void setSolidColors(ColorStateList colors) { 1718e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mGradientColors = null; 1719e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mSolidColors = colors; 1720e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy computeOpacity(); 1721e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy } 1722e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 1723e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy private void computeOpacity() { 1724c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik mOpaqueOverBounds = false; 1725c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik mOpaqueOverShape = false; 172639824f685c33f8aabbe9526b4cc79b7411e8b37fRaph Levien 1727e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (mGradientColors != null) { 1728e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette for (int i = 0; i < mGradientColors.length; i++) { 1729e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (!isOpaque(mGradientColors[i])) { 1730e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy return; 1731e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy } 1732e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy } 1733e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy } 1734e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 173522cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase // An unfilled shape is not opaque over bounds or shape 1736e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (mGradientColors == null && mSolidColors == null) { 173722cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase return; 173822cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase } 173922cf0b0cb856336d36961280b1e968a91d4488d5Chet Haase 1740c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik // Colors are opaque, so opaqueOverShape=true, 1741c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik mOpaqueOverShape = true; 1742c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik // and opaqueOverBounds=true if shape fills bounds 1743c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik mOpaqueOverBounds = mShape == RECTANGLE 1744c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik && mRadius <= 0 1745c49e3ce6c6ac5100dc5a73c6bd12cbfda4d4ca76Chris Craik && mRadiusArray == null; 1746e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy } 1747e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 1748e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette public void setStroke(int width, ColorStateList colors, float dashWidth, float dashGap) { 1749a211dd28b93473c452d68432c602d5209b01c178Alan Viverette mStrokeWidth = width; 1750e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette mStrokeColors = colors; 17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokeDashWidth = dashWidth; 17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokeDashGap = dashGap; 1753e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy computeOpacity(); 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCornerRadius(float radius) { 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (radius < 0) { 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project radius = 0; 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadius = radius; 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadiusArray = null; 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1763e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCornerRadii(float[] radii) { 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadiusArray = radii; 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (radii == null) { 17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRadius = 0; 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1770e91aa0fa64db892194ba82ec7d41df6fb9185471Romain Guy 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSize(int width, int height) { 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidth = width; 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeight = height; 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1776861621eb8a3bd8896bc00c4c5bc8af6816215e21Alan Viverette public void setGradientRadius(float gradientRadius, int type) { 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGradientRadius = gradientRadius; 1778b32b8a52a3aa2d9d7b5ffaea28e0e31cb077f5e0Alan Viverette mGradientRadiusType = type; 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1782888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette static boolean isOpaque(int color) { 1783888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette return ((color >> 24) & 0xff) == 0xff; 1784888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette } 1785888b4cf73c9663be37c4faa1249cef1a6a8f8c38Alan Viverette 178652b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette /** 178752b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * Creates a new themed GradientDrawable based on the specified constant state. 178852b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * <p> 178952b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * The resulting drawable is guaranteed to have a new constant state. 179052b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * 179152b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette * @param state Constant state from which the drawable inherits 179252b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette */ 179345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette private GradientDrawable(GradientState state, Resources res) { 179417cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette mGradientState = state; 179552b999f0721b53e9c6e18a4bd664e89aeb65b2d5Alan Viverette 179645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette updateLocalState(res); 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette private void updateLocalState(Resources res) { 180045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette final GradientState state = mGradientState; 180145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 1802e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (state.mSolidColors != null) { 1803519494e207322581075c8ea884fde9d33bb9209eAlan Viverette final int[] currentState = getState(); 1804e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int stateColor = state.mSolidColors.getColorForState(currentState, 0); 1805519494e207322581075c8ea884fde9d33bb9209eAlan Viverette mFillPaint.setColor(stateColor); 1806e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette } else if (state.mGradientColors == null) { 1807cf8675ee176a375f873792684d38a47f78348dffRomain Guy // If we don't have a solid color and we don't have a gradient, 1808cf8675ee176a375f873792684d38a47f78348dffRomain Guy // the app is stroking the shape, set the color to the default 1809cf8675ee176a375f873792684d38a47f78348dffRomain Guy // value of state.mSolidColor 1810cf8675ee176a375f873792684d38a47f78348dffRomain Guy mFillPaint.setColor(0); 18114d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette } else { 18124d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette // Otherwise, make sure the fill alpha is maxed out. 18134d971c1fa0c71400ff1e843b8d8b4826d0aece16Alan Viverette mFillPaint.setColor(Color.BLACK); 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 181517dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPadding = state.mPadding; 181717dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.mStrokeWidth >= 0) { 18196a49ddef62865c1b245ad60a13c334f0ffaf1a5fChris Craik mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setStyle(Paint.Style.STROKE); 18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setStrokeWidth(state.mStrokeWidth); 182217dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette 1823e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette if (state.mStrokeColors != null) { 1824083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette final int[] currentState = getState(); 1825e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette final int strokeStateColor = state.mStrokeColors.getColorForState( 1826083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette currentState, 0); 1827083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette mStrokePaint.setColor(strokeStateColor); 1828083f5518d73e15d70ceb5c0cbc1370eda1928252Alan Viverette } 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.mStrokeDashWidth != 0.0f) { 183117dafdc8d8cb92a03294657d3a6e36c9c546d130Alan Viverette final DashPathEffect e = new DashPathEffect( 18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new float[] { state.mStrokeDashWidth, state.mStrokeDashGap }, 0); 18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStrokePaint.setPathEffect(e); 18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18363ad771b384b55bc0b9ee9519f457ea7093bb0b74Alan Viverette 1837daec594370f0e47bf07d0c9c968e3c5dfedf0bb5Alan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 183845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette mGradientIsDirty = true; 183945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 184045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette state.computeOpacity(); 18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1843