GradientColor.java revision dbee9bb342cdfaa5155b1918f90262c05e2464cb
1dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu/*
2dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * Copyright (C) 2016 The Android Open Source Project
3dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu *
4dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * you may not use this file except in compliance with the License.
6dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * You may obtain a copy of the License at
7dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu *
8dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu *
10dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * Unless required by applicable law or agreed to in writing, software
11dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * See the License for the specific language governing permissions and
14dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu * limitations under the License.
15dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu */
16dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
17dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhupackage android.content.res;
18dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
19dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.annotation.ColorInt;
20dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.annotation.NonNull;
21dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.annotation.Nullable;
22dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.content.res.Resources.Theme;
23dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
24dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport com.android.internal.R;
25dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport com.android.internal.util.GrowingArrayUtils;
26dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
27dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport org.xmlpull.v1.XmlPullParser;
28dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport org.xmlpull.v1.XmlPullParserException;
29dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
30dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.graphics.LinearGradient;
31dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.graphics.RadialGradient;
32dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.graphics.Shader;
33dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.graphics.SweepGradient;
34dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.graphics.drawable.GradientDrawable;
35dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.util.AttributeSet;
36dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.util.Log;
37dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport android.util.Xml;
38dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
39dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhuimport java.io.IOException;
40dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
41dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
42dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhupublic class GradientColor extends ComplexColor {
43dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private static final String TAG = "GradientColor";
44dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
45dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private static final boolean DBG_GRADIENT = false;
46dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
47dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /** Lazily-created factory for this GradientColor. */
48dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private GradientColorFactory mFactory;
49dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
50dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mChangingConfigurations;
51dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mDefaultColor;
52dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
53dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    // After parsing all the attributes from XML, this shader is the ultimate result containing
54dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    // all the XML information.
55dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private Shader mShader = null;
56dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
57dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    // Below are the attributes at the root element <gradient>
58dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mGradientType = GradientDrawable.LINEAR_GRADIENT;
59dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
60dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mCenterX = 0f;
61dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mCenterY = 0f;
62dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
63dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mStartX = 0f;
64dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mStartY = 0f;
65dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mEndX = 0f;
66dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mEndY = 0f;
67dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
68dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mStartColor = 0;
69dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mCenterColor = 0;
70dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int mEndColor = 0;
71dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private boolean mHasCenterColor = false;
72dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
73dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float mGradientRadius = 0f;
74dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
75dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    // Below are the attributes for the <item> element.
76dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int[] mItemColors;
77dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private float[] mItemOffsets;
78dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
79dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    // Theme attributes for the root and item elements.
80dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int[] mThemeAttrs;
81dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private int[][] mItemsThemeAttrs;
82dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
83dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private GradientColor() {
84dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
85dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
86dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private GradientColor(GradientColor copy) {
87dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (copy != null) {
88dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mChangingConfigurations = copy.mChangingConfigurations;
89dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mDefaultColor = copy.mDefaultColor;
90dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mShader = copy.mShader;
91dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mGradientType = copy.mGradientType;
92dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mCenterX = copy.mCenterX;
93dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mCenterY = copy.mCenterY;
94dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mStartX = copy.mStartX;
95dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mStartY = copy.mStartY;
96dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mEndX = copy.mEndX;
97dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mEndY = copy.mEndY;
98dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mStartColor = copy.mStartColor;
99dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mCenterColor = copy.mCenterColor;
100dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mEndColor = copy.mEndColor;
101dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mHasCenterColor = copy.mHasCenterColor;
102dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mGradientRadius = copy.mGradientRadius;
103dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
104dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (copy.mItemColors != null) {
105dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemColors = copy.mItemColors.clone();
106dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
107dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (copy.mItemOffsets != null) {
108dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemOffsets = copy.mItemOffsets.clone();
109dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
110dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
111dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (copy.mThemeAttrs != null) {
112dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mThemeAttrs = copy.mThemeAttrs.clone();
113dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
114dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (copy.mItemsThemeAttrs != null) {
115dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemsThemeAttrs = copy.mItemsThemeAttrs.clone();
116dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
117dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
118dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
119dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
120dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
121dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Update the root level's attributes, either for inflate or applyTheme.
122dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
123dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void updateRootElementState(TypedArray a) {
124dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // Extract the theme attributes, if any.
125dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mThemeAttrs = a.extractThemeAttrs();
126dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
127dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mStartX = a.getFloat(
128dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_startX, mStartX);
129dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mStartY = a.getFloat(
130dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_startY, mStartY);
131dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mEndX = a.getFloat(
132dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_endX, mEndX);
133dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mEndY = a.getFloat(
134dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_endY, mEndY);
135dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
136dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mCenterX = a.getFloat(
137dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_centerX, mCenterX);
138dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mCenterY = a.getFloat(
139dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_centerY, mCenterY);
140dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
141dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mGradientType = a.getInt(
142dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_type, mGradientType);
143dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
144dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mStartColor = a.getColor(
145dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_startColor, mStartColor);
146dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mHasCenterColor |= a.hasValue(
147dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_centerColor);
148dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mCenterColor = a.getColor(
149dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_centerColor, mCenterColor);
150dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mEndColor = a.getColor(
151dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                R.styleable.GradientColor_endColor, mEndColor);
152dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
153dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (DBG_GRADIENT) {
154dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            Log.v(TAG, "hasCenterColor is " + mHasCenterColor);
155dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (mHasCenterColor) {
156dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                Log.v(TAG, "centerColor:" + mCenterColor);
157dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
158dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            Log.v(TAG, "startColor: " + mStartColor);
159dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            Log.v(TAG, "endColor: " + mEndColor);
160dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
161dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
162dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mGradientRadius = a.getFloat(R.styleable.GradientColor_gradientRadius,
163dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mGradientRadius);
164dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
165dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
166dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
167dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Check if the XML content is valid.
168dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     *
169dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @throws XmlPullParserException if errors were found.
170dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
171dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void validateXmlContent() throws XmlPullParserException {
172dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mGradientRadius <= 0
173dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                && mGradientType == GradientDrawable.RADIAL_GRADIENT) {
174dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throw new XmlPullParserException(
175dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    "<gradient> tag requires 'gradientRadius' "
176dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                            + "attribute with radial type");
177dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
178dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
179dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
180dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
181dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * The shader information will be applied to the native VectorDrawable's path.
182dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @hide
183dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
184dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public Shader getShader() {
185dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return mShader;
186dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
187dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
188dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
189dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * A public method to create GradientColor from a XML resource.
190dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
191dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public static GradientColor createFromXml(Resources r, XmlResourceParser parser, Theme theme)
192dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throws XmlPullParserException, IOException {
193dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final AttributeSet attrs = Xml.asAttributeSet(parser);
194dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
195dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int type;
196dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        while ((type = parser.next()) != XmlPullParser.START_TAG
197dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                && type != XmlPullParser.END_DOCUMENT) {
198dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            // Seek parser to start tag.
199dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
200dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
201dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (type != XmlPullParser.START_TAG) {
202dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throw new XmlPullParserException("No start tag found");
203dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
204dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
205dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return createFromXmlInner(r, parser, attrs, theme);
206dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
207dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
208dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
209dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Create from inside an XML document. Called on a parser positioned at a
210dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * tag in an XML document, tries to create a GradientColor from that tag.
211dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     *
212dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @return A new GradientColor for the current tag.
213dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @throws XmlPullParserException if the current tag is not &lt;gradient>
214dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
215dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @NonNull
216dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    static GradientColor createFromXmlInner(@NonNull Resources r,
217dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
218dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throws XmlPullParserException, IOException {
219dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final String name = parser.getName();
220dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (!name.equals("gradient")) {
221dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throw new XmlPullParserException(
222dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    parser.getPositionDescription() + ": invalid gradient color tag " + name);
223dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
224dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
225dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final GradientColor gradientColor = new GradientColor();
226dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        gradientColor.inflate(r, parser, attrs, theme);
227dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return gradientColor;
228dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
229dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
230dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
231dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Fill in this object based on the contents of an XML "gradient" element.
232dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
233dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
234dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            @NonNull AttributeSet attrs, @Nullable Theme theme)
235dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throws XmlPullParserException, IOException {
236dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final TypedArray a = Resources.obtainAttributes(r, theme, attrs, R.styleable.GradientColor);
237dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        updateRootElementState(a);
238dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mChangingConfigurations |= a.getChangingConfigurations();
239dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        a.recycle();
240dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
241dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // Check correctness and throw exception if errors found.
242dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        validateXmlContent();
243dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
244dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        inflateChildElements(r, parser, attrs, theme);
245dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
246dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        onColorsChange();
247dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
248dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
249dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
250dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Inflates child elements "item"s for each color stop.
251dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     *
252dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Note that at root level, we need to save ThemeAttrs for theme applied later.
253dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Here similarly, at each child item, we need to save the theme's attributes, and apply theme
254dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * later as applyItemsAttrsTheme().
255dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
256dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void inflateChildElements(@NonNull Resources r, @NonNull XmlPullParser parser,
257dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            @NonNull AttributeSet attrs, @NonNull Theme theme)
258dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            throws XmlPullParserException, IOException {
259dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final int innerDepth = parser.getDepth() + 1;
260dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int type;
261dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int depth;
262dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
263dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // Pre-allocate the array with some size, for better performance.
264dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        float[] offsetList = new float[20];
265dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int[] colorList = new int[offsetList.length];
266dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int[][] themeAttrsList = new int[offsetList.length][];
267dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
268dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int listSize = 0;
269dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        boolean hasUnresolvedAttrs = false;
270dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
271dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                && ((depth = parser.getDepth()) >= innerDepth
272dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                || type != XmlPullParser.END_TAG)) {
273dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (type != XmlPullParser.START_TAG) {
274dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                continue;
275dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
276dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (depth > innerDepth || !parser.getName().equals("item")) {
277dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                continue;
278dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
279dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
280dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            final TypedArray a = Resources.obtainAttributes(r, theme, attrs,
281dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    R.styleable.GradientColorItem);
282dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            boolean hasColor = a.hasValue(R.styleable.GradientColorItem_color);
283dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            boolean hasOffset = a.hasValue(R.styleable.GradientColorItem_offset);
284dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (!hasColor || !hasOffset) {
285dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                throw new XmlPullParserException(
286dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                        parser.getPositionDescription()
287dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                                + ": <item> tag requires a 'color' attribute and a 'offset' "
288dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                                + "attribute!");
289dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
290dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
291dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            final int[] themeAttrs = a.extractThemeAttrs();
292dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            int color = a.getColor(R.styleable.GradientColorItem_color, 0);
293dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            float offset = a.getFloat(R.styleable.GradientColorItem_offset, 0);
294dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
295dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (DBG_GRADIENT) {
296dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                Log.v(TAG, "new item color " + color + " " + Integer.toHexString(color));
297dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                Log.v(TAG, "offset" + offset);
298dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
299dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mChangingConfigurations |= a.getChangingConfigurations();
300dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            a.recycle();
301dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
302dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (themeAttrs != null) {
303dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                hasUnresolvedAttrs = true;
304dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
305dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
306dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            colorList = GrowingArrayUtils.append(colorList, listSize, color);
307dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            offsetList = GrowingArrayUtils.append(offsetList, listSize, offset);
308dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            themeAttrsList = GrowingArrayUtils.append(themeAttrsList, listSize, themeAttrs);
309dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            listSize++;
310dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
311dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (listSize > 0) {
312dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (hasUnresolvedAttrs) {
313dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemsThemeAttrs = new int[listSize][];
314dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                System.arraycopy(themeAttrsList, 0, mItemsThemeAttrs, 0, listSize);
315dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            } else {
316dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemsThemeAttrs = null;
317dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
318dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
319dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mItemColors = new int[listSize];
320dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mItemOffsets = new float[listSize];
321dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            System.arraycopy(colorList, 0, mItemColors, 0, listSize);
322dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            System.arraycopy(offsetList, 0, mItemOffsets, 0, listSize);
323dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
324dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
325dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
326dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
327dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Apply theme to all the items.
328dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
329dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void applyItemsAttrsTheme(Theme t) {
330dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mItemsThemeAttrs == null) {
331dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            return;
332dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
333dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
334dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        boolean hasUnresolvedAttrs = false;
335dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
336dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final int[][] themeAttrsList = mItemsThemeAttrs;
337dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final int N = themeAttrsList.length;
338dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        for (int i = 0; i < N; i++) {
339dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (themeAttrsList[i] != null) {
340dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                final TypedArray a = t.resolveAttributes(themeAttrsList[i],
341dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                        R.styleable.GradientColorItem);
342dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
343dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                // Extract the theme attributes, if any, before attempting to
344dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                // read from the typed array. This prevents a crash if we have
345dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                // unresolved attrs.
346dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                themeAttrsList[i] = a.extractThemeAttrs(themeAttrsList[i]);
347dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                if (themeAttrsList[i] != null) {
348dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    hasUnresolvedAttrs = true;
349dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                }
350dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
351dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemColors[i] = a.getColor(R.styleable.GradientColorItem_color, mItemColors[i]);
352dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mItemOffsets[i] = a.getFloat(R.styleable.GradientColorItem_offset, mItemOffsets[i]);
353dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                if (DBG_GRADIENT) {
354dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    Log.v(TAG, "applyItemsAttrsTheme Colors[i] " + i + " " +
355dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                            Integer.toHexString(mItemColors[i]));
356dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    Log.v(TAG, "Offsets[i] " + i + " " + mItemOffsets[i]);
357dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                }
358dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
359dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                // Account for any configuration changes.
360dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mChangingConfigurations |= a.getChangingConfigurations();
361dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
362dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                a.recycle();
363dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
364dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
365dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
366dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (!hasUnresolvedAttrs) {
367dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mItemsThemeAttrs = null;
368dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
369dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
370dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
371dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void onColorsChange() {
372dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        int[] tempColors = null;
373dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        float[] tempOffsets = null;
374dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
375dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mItemColors != null) {
376dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            int length = mItemColors.length;
377dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            tempColors = new int[length];
378dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            tempOffsets = new float[length];
379dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
380dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            for (int i = 0; i < length; i++) {
381dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[i] = mItemColors[i];
382dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempOffsets[i] = mItemOffsets[i];
383dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
384dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        } else {
385dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (mHasCenterColor) {
386dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors = new int[3];
387dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[0] = mStartColor;
388dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[1] = mCenterColor;
389dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[2] = mEndColor;
390dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
391dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempOffsets = new float[3];
392dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempOffsets[0] = 0.0f;
393dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                // Since 0.5f is default value, try to take the one that isn't 0.5f
394dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempOffsets[1] = 0.5f;
395dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempOffsets[2] = 1f;
396dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            } else {
397dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors = new int[2];
398dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[0] = mStartColor;
399dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                tempColors[1] = mEndColor;
400dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
401dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
402dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (tempColors.length < 2) {
403dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            Log.w(TAG, "<gradient> tag requires 2 color values specified!" + tempColors.length
404dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    + " " + tempColors);
405dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
406dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
407dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mGradientType == GradientDrawable.LINEAR_GRADIENT) {
408dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mShader = new LinearGradient(mStartX, mStartY, mEndX, mEndY, tempColors, tempOffsets,
409dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                    Shader.TileMode.CLAMP);
410dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        } else {
411dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            if (mGradientType == GradientDrawable.RADIAL_GRADIENT) {
412dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mShader = new RadialGradient(mCenterX, mCenterY, mGradientRadius, tempColors,
413dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                        tempOffsets, Shader.TileMode.CLAMP);
414dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            } else {
415dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu                mShader = new SweepGradient(mCenterX, mCenterY, tempColors, tempOffsets);
416dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            }
417dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
418dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mDefaultColor = tempColors[0];
419dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
420dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
421dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
422dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * For Gradient color, the default color is not very useful, since the gradient will override
423dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * the color information anyway.
424dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
425dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @Override
426dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @ColorInt
427dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public int getDefaultColor() {
428dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return mDefaultColor;
429dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
430dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
431dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
432dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Similar to ColorStateList, setup constant state and its factory.
433dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @hide only for resource preloading
434dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
435dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @Override
436dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public ConstantState<ComplexColor> getConstantState() {
437dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mFactory == null) {
438dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mFactory = new GradientColorFactory(this);
439dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
440dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return mFactory;
441dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
442dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
443dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private static class GradientColorFactory extends ConstantState<ComplexColor> {
444dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        private final GradientColor mSrc;
445dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
446dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        public GradientColorFactory(GradientColor src) {
447dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            mSrc = src;
448dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
449dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
450dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        @Override
451dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        public int getChangingConfigurations() {
452dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            return mSrc.mChangingConfigurations;
453dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
454dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
455dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        @Override
456dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        public GradientColor newInstance() {
457dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            return mSrc;
458dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
459dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
460dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        @Override
461dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        public GradientColor newInstance(Resources res, Theme theme) {
462dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            return mSrc.obtainForTheme(theme);
463dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
464dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
465dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
466dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
467dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Returns an appropriately themed gradient color.
468dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     *
469dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @param t the theme to apply
470dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @return a copy of the gradient color the theme applied, or the
471dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * gradient itself if there were no unresolved theme
472dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * attributes
473dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @hide only for resource preloading
474dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
475dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @Override
476dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public GradientColor obtainForTheme(Theme t) {
477dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (t == null || !canApplyTheme()) {
478dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            return this;
479dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
480dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
481dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final GradientColor clone = new GradientColor(this);
482dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        clone.applyTheme(t);
483dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return clone;
484dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
485dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
486dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void applyTheme(Theme t) {
487dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mThemeAttrs != null) {
488dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            applyRootAttrsTheme(t);
489dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
490dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        if (mItemsThemeAttrs != null) {
491dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu            applyItemsAttrsTheme(t);
492dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        }
493dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        onColorsChange();
494dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
495dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
496dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    private void applyRootAttrsTheme(Theme t) {
497dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.GradientColor);
498dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // mThemeAttrs will be set to null if if there are no theme attributes in the
499dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // typed array.
500dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mThemeAttrs = a.extractThemeAttrs(mThemeAttrs);
501dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // merging the attributes update inside the updateRootElementState().
502dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        updateRootElementState(a);
503dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
504dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        // Account for any configuration changes.
505dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        mChangingConfigurations |= a.getChangingConfigurations();
506dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        a.recycle();
507dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
508dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
509dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
510dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    /**
511dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * Returns whether a theme can be applied to this gradient color, which
512dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * usually indicates that the gradient color has unresolved theme
513dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * attributes.
514dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     *
515dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @return whether a theme can be applied to this gradient color.
516dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     * @hide only for resource preloading
517dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu     */
518dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    @Override
519dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    public boolean canApplyTheme() {
520dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu        return mThemeAttrs != null || mItemsThemeAttrs != null;
521dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu    }
522dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
523dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu}
524