VectorDrawable.java revision 34c623cbf3677820c4170f24c5211f663dda91f7
1abb7d134c02ac60091108c491dafb00877093170John Hoford/*
2abb7d134c02ac60091108c491dafb00877093170John Hoford * Copyright (C) 2014 The Android Open Source Project
3abb7d134c02ac60091108c491dafb00877093170John Hoford *
4abb7d134c02ac60091108c491dafb00877093170John Hoford * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5abb7d134c02ac60091108c491dafb00877093170John Hoford * in compliance with the License. You may obtain a copy of the License at
6abb7d134c02ac60091108c491dafb00877093170John Hoford *
7abb7d134c02ac60091108c491dafb00877093170John Hoford * http://www.apache.org/licenses/LICENSE-2.0
8abb7d134c02ac60091108c491dafb00877093170John Hoford *
9abb7d134c02ac60091108c491dafb00877093170John Hoford * Unless required by applicable law or agreed to in writing, software distributed under the License
10abb7d134c02ac60091108c491dafb00877093170John Hoford * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11abb7d134c02ac60091108c491dafb00877093170John Hoford * or implied. See the License for the specific language governing permissions and limitations under
12abb7d134c02ac60091108c491dafb00877093170John Hoford * the License.
13abb7d134c02ac60091108c491dafb00877093170John Hoford */
14abb7d134c02ac60091108c491dafb00877093170John Hoford
15abb7d134c02ac60091108c491dafb00877093170John Hofordpackage android.graphics.drawable;
16abb7d134c02ac60091108c491dafb00877093170John Hoford
1717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viveretteimport android.annotation.NonNull;
18b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList;
19abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources;
20abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources.Theme;
214b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viveretteimport android.content.res.TypedArray;
22482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghuiimport android.graphics.Bitmap;
23abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Canvas;
242af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghuiimport android.graphics.Color;
25abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.ColorFilter;
26abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Matrix;
27abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Paint;
28abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Path;
29abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PathMeasure;
30abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PixelFormat;
31b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuffColorFilter;
32abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Rect;
33abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Region;
34b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
35e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.ArrayMap;
36abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.AttributeSet;
37738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghuiimport android.util.LayoutDirection;
38abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.Log;
39cf4832f69c8786b098ce18c24319021f8cd6733aztenghuiimport android.util.PathParser;
404b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport android.util.Xml;
41abb7d134c02ac60091108c491dafb00877093170John Hoford
42abb7d134c02ac60091108c491dafb00877093170John Hofordimport com.android.internal.R;
43abb7d134c02ac60091108c491dafb00877093170John Hoford
44abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParser;
45abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParserException;
46abb7d134c02ac60091108c491dafb00877093170John Hoford
47abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.io.IOException;
48abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.util.ArrayList;
494d24caf1dec2babf273b18c99638fe2a0635ced4ztenghuiimport java.util.Stack;
504b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
51abb7d134c02ac60091108c491dafb00877093170John Hoford/**
526beeb75723cec42603b47664bce794a2b97d7bacChet Haase * This lets you create a drawable based on an XML vector graphic. It can be
53d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * defined in an XML file with the <code>&lt;vector></code> element.
54abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
5546e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * The vector drawable has the following elements:
56abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
57177dffd869ff1f5bdf816faead01a7dc4980bf75ztenghui * <dt><code>&lt;vector></code></dt>
58a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
59a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Used to defined a vector drawable
60a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
61c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt>
62c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of this vector drawable.</dd>
63a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:width</code></dt>
64a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Used to defined the intrinsic width of the drawable.
65a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd>
66a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:height</code></dt>
67a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Used to defined the intrinsic height the drawable.
68a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd>
69a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportWidth</code></dt>
70a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Used to defined the width of the viewport space. Viewport is basically
71a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd>
72a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportHeight</code></dt>
73a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Used to defined the height of the viewport space. Viewport is basically
74a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd>
75a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tint</code></dt>
76a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
77a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tintMode</code></dt>
78a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
79a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:autoMirrored</code></dt>
80a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
81a95c8abb366d9c39450513335f550b56da13b30aztenghui * RTL (right-to-left).</dd>
82c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:alpha</code></dt>
83c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>The opacity of this drawable.</dd>
84a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
85a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
86a95c8abb366d9c39450513335f550b56da13b30aztenghui *
87a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
886d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dt><code>&lt;group></code></dt>
89452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>Defines a group of paths or subgroups, plus transformation information.
90452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * The transformations are defined in the same coordinates as the viewport.
91a95c8abb366d9c39450513335f550b56da13b30aztenghui * And the transformations are applied in the order of scale, rotate then translate.
92a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
93c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt>
94c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of the group.</dd>
95a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:rotation</code></dt>
96a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The degrees of rotation of the group.</dd>
97a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pivotX</code></dt>
98a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The X coordinate of the pivot for the scale and rotation of the group.
99a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
100a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pivotY</code></dt>
101a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
102a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
103a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleX</code></dt>
104a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the X Coordinate.</dd>
105a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleY</code></dt>
106a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the Y coordinate.</dd>
107a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateX</code></dt>
108a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the X coordinate.
109a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
110a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateY</code></dt>
111a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the Y coordinate.
112a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
113a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
114a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
115a95c8abb366d9c39450513335f550b56da13b30aztenghui *
116a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
117abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;path></code></dt>
1186d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dd>Defines paths to be drawn.
119abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
120a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt>
121a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the path.</dd>
122a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt>
12346e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * <dd>Defines path string. This is using exactly same format as "d" attribute
124a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data. This is defined in the viewport space.</dd>
125a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:fillColor</code></dt>
126a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui * <dd>Defines the color to fill the path (none if not present).</dd>
127a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeColor</code></dt>
128d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Defines the color to draw the path outline (none if not present).</dd>
129a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeWidth</code></dt>
130a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The width a path stroke.</dd>
1312e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:strokeAlpha</code></dt>
1322e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity of a path stroke.</dd>
1332e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:fillAlpha</code></dt>
1342e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity to fill the path with.</dd>
135a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathStart</code></dt>
136a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
137a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathEnd</code></dt>
138a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
139a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathOffset</code></dt>
140a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Shift trim region (allows showed region to include the start and end), in the range
141a95c8abb366d9c39450513335f550b56da13b30aztenghui * from 0 to 1.</dd>
142a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineCap</code></dt>
143a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
144a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineJoin</code></dt>
145a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
146a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeMiterLimit</code></dt>
147a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the Miter limit for a stroked path.</dd>
148a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
149a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
150a95c8abb366d9c39450513335f550b56da13b30aztenghui *
151a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
152a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>&lt;clip-path></code></dt>
1536fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * <dd>Defines path to be the current clip. Note that the clip path only apply to
1546fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * the current group and its children.
155a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
156a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt>
157a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the clip path.</dd>
158a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt>
159a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines clip path string. This is using exactly same format as "d" attribute
160a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data.</dd>
161a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
162abb7d134c02ac60091108c491dafb00877093170John Hoford * </dl>
163a95c8abb366d9c39450513335f550b56da13b30aztenghui * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
164a95c8abb366d9c39450513335f550b56da13b30aztenghui * <pre>
165a95c8abb366d9c39450513335f550b56da13b30aztenghui * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android";
166a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:height=&quot;64dp&quot;
167a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:width=&quot;64dp&quot;
168a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportHeight=&quot;600&quot;
169a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportWidth=&quot;600&quot; &gt;
170a95c8abb366d9c39450513335f550b56da13b30aztenghui *     &lt;group
171a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:name=&quot;rotationGroup&quot;
172a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:pivotX=&quot;300.0&quot;
173a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:pivotY=&quot;300.0&quot;
174a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:rotation=&quot;45.0&quot; &gt;
175a95c8abb366d9c39450513335f550b56da13b30aztenghui *         &lt;path
176a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:name=&quot;v&quot;
177a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:fillColor=&quot;#000000&quot;
178a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
179a95c8abb366d9c39450513335f550b56da13b30aztenghui *     &lt;/group&gt;
180a95c8abb366d9c39450513335f550b56da13b30aztenghui * &lt;/vector&gt;
181a95c8abb366d9c39450513335f550b56da13b30aztenghui * </pre></li>
182abb7d134c02ac60091108c491dafb00877093170John Hoford */
183a95c8abb366d9c39450513335f550b56da13b30aztenghui
184abb7d134c02ac60091108c491dafb00877093170John Hofordpublic class VectorDrawable extends Drawable {
1859453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private static final String LOGTAG = VectorDrawable.class.getSimpleName();
1869453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
187a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static final String SHAPE_CLIP_PATH = "clip-path";
1886d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui    private static final String SHAPE_GROUP = "group";
189abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_PATH = "path";
190abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VECTOR = "vector";
191abb7d134c02ac60091108c491dafb00877093170John Hoford
192abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_BUTT = 0;
193abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_ROUND = 1;
194abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_SQUARE = 2;
1959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
196abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_MITER = 0;
197abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_ROUND = 1;
198abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_BEVEL = 2;
1999453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2004d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private static final boolean DBG_VECTOR_DRAWABLE = false;
2014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
20255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private VectorDrawableState mVectorState;
203e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
204b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    private PorterDuffColorFilter mTintFilter;
205b07b086bd42181f62718a6394b56be3917b12511Alan Viverette    private ColorFilter mColorFilter;
206b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
20755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private boolean mMutated;
20855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
209482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
210482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // caching the bitmap by default is allowed.
211482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    private boolean mAllowCaching = true;
212482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
213abb7d134c02ac60091108c491dafb00877093170John Hoford    public VectorDrawable() {
21455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState = new VectorDrawableState();
215abb7d134c02ac60091108c491dafb00877093170John Hoford    }
216abb7d134c02ac60091108c491dafb00877093170John Hoford
21717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette    private VectorDrawable(@NonNull VectorDrawableState state) {
21817cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette        mVectorState = state;
219b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
220abb7d134c02ac60091108c491dafb00877093170John Hoford    }
221abb7d134c02ac60091108c491dafb00877093170John Hoford
22255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
22355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public Drawable mutate() {
22455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        if (!mMutated && super.mutate() == this) {
22555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVectorState = new VectorDrawableState(mVectorState);
22655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mMutated = true;
22755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
22855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return this;
22955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
23055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
231727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
232727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
233727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
234727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
235727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
236727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
237727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
238727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
239e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    Object getTargetByName(String name) {
24055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
241e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
242e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
243abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
244abb7d134c02ac60091108c491dafb00877093170John Hoford    public ConstantState getConstantState() {
24555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
24655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState;
247abb7d134c02ac60091108c491dafb00877093170John Hoford    }
248abb7d134c02ac60091108c491dafb00877093170John Hoford
2494554a6a5137d8e9bdfb623ad84ff344a48b7eb9dAlan Viverette    @Override
250abb7d134c02ac60091108c491dafb00877093170John Hoford    public void draw(Canvas canvas) {
2514b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        final Rect bounds = getBounds();
25234c623cbf3677820c4170f24c5211f663dda91f7ztenghui        if (bounds.width() <= 0 || bounds.height() <= 0) {
25334c623cbf3677820c4170f24c5211f663dda91f7ztenghui            // Nothing to draw
2541968201b44567262e7b2e382eee3d88990748d89Dan Sandler            return;
2551968201b44567262e7b2e382eee3d88990748d89Dan Sandler        }
2561968201b44567262e7b2e382eee3d88990748d89Dan Sandler
2570670f029a4e59448aa53b46a98e60dff6404f360ztenghui        final int saveCount = canvas.save();
258738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        final boolean needMirroring = needMirroring();
259738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
2604b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.translate(bounds.left, bounds.top);
261738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (needMirroring) {
262738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            canvas.translate(bounds.width(), 0);
263738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            canvas.scale(-1.0f, 1.0f);
264738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
265482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
266b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        // Color filters always override tint filters.
267b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter;
268b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
269482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        if (!mAllowCaching) {
2708490354dc651dd8f25036ef0dda7917fb33013edztenghui            // AnimatedVectorDrawable
2718490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (!mVectorState.hasTranslucentRoot()) {
272b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                mVectorState.mVPathRenderer.draw(
273b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                        canvas, bounds.width(), bounds.height(), colorFilter);
2748490354dc651dd8f25036ef0dda7917fb33013edztenghui            } else {
2758490354dc651dd8f25036ef0dda7917fb33013edztenghui                mVectorState.createCachedBitmapIfNeeded(bounds);
2768490354dc651dd8f25036ef0dda7917fb33013edztenghui                mVectorState.updateCachedBitmap(bounds);
277b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
2788490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
279482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        } else {
2808490354dc651dd8f25036ef0dda7917fb33013edztenghui            // Static Vector Drawable case.
2818490354dc651dd8f25036ef0dda7917fb33013edztenghui            mVectorState.createCachedBitmapIfNeeded(bounds);
2828490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (!mVectorState.canReuseCache()) {
2838490354dc651dd8f25036ef0dda7917fb33013edztenghui                mVectorState.updateCachedBitmap(bounds);
284482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                mVectorState.updateCacheStates();
285482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
286b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter);
287482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
288738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
2894b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.restoreToCount(saveCount);
290abb7d134c02ac60091108c491dafb00877093170John Hoford    }
291abb7d134c02ac60091108c491dafb00877093170John Hoford
292abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
293e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getAlpha() {
294e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
295e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
296e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
297e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
298abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setAlpha(int alpha) {
2992af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
3002af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
301abb7d134c02ac60091108c491dafb00877093170John Hoford            invalidateSelf();
302abb7d134c02ac60091108c491dafb00877093170John Hoford        }
303abb7d134c02ac60091108c491dafb00877093170John Hoford    }
304abb7d134c02ac60091108c491dafb00877093170John Hoford
305abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
306abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setColorFilter(ColorFilter colorFilter) {
307b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        mColorFilter = colorFilter;
308fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        invalidateSelf();
309abb7d134c02ac60091108c491dafb00877093170John Hoford    }
310abb7d134c02ac60091108c491dafb00877093170John Hoford
311abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
312a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintList(ColorStateList tint) {
313b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
314a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (state.mTint != tint) {
315b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTint = tint;
316a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
317a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            invalidateSelf();
318a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        }
319a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    }
320b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
321a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    @Override
322a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintMode(Mode tintMode) {
323a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        final VectorDrawableState state = mVectorState;
324a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (state.mTintMode != tintMode) {
325a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            state.mTintMode = tintMode;
326a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
327b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            invalidateSelf();
328b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
329b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
330b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
331b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
332607bd848269fb802550e63aa61945790616f97a7Alan Viverette    public boolean isStateful() {
333607bd848269fb802550e63aa61945790616f97a7Alan Viverette        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
334607bd848269fb802550e63aa61945790616f97a7Alan Viverette                && mVectorState.mTint.isStateful());
335607bd848269fb802550e63aa61945790616f97a7Alan Viverette    }
336607bd848269fb802550e63aa61945790616f97a7Alan Viverette
337607bd848269fb802550e63aa61945790616f97a7Alan Viverette    @Override
338b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    protected boolean onStateChange(int[] stateSet) {
339b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
340b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != null && state.mTintMode != null) {
341b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
342607bd848269fb802550e63aa61945790616f97a7Alan Viverette            invalidateSelf();
343b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            return true;
344b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
345b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        return false;
346b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
347b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
348b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
349abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getOpacity() {
350abb7d134c02ac60091108c491dafb00877093170John Hoford        return PixelFormat.TRANSLUCENT;
351abb7d134c02ac60091108c491dafb00877093170John Hoford    }
352abb7d134c02ac60091108c491dafb00877093170John Hoford
353abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
354abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicWidth() {
355ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
356abb7d134c02ac60091108c491dafb00877093170John Hoford    }
357abb7d134c02ac60091108c491dafb00877093170John Hoford
358abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
359abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicHeight() {
360ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
361abb7d134c02ac60091108c491dafb00877093170John Hoford    }
362abb7d134c02ac60091108c491dafb00877093170John Hoford
363abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
3649453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public boolean canApplyTheme() {
365d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme();
3669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
3679453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3689453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    @Override
3699453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public void applyTheme(Theme t) {
3709453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        super.applyTheme(t);
3719453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3729453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        final VectorDrawableState state = mVectorState;
37345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state == null) {
37445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return;
37545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
37645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
37745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mThemeAttrs != null) {
37845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final TypedArray a = t.resolveAttributes(
37945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    state.mThemeAttrs, R.styleable.VectorDrawable);
380607bd848269fb802550e63aa61945790616f97a7Alan Viverette            try {
381607bd848269fb802550e63aa61945790616f97a7Alan Viverette                state.mCacheDirty = true;
382607bd848269fb802550e63aa61945790616f97a7Alan Viverette                updateStateFromTypedArray(a);
383607bd848269fb802550e63aa61945790616f97a7Alan Viverette            } catch (XmlPullParserException e) {
384607bd848269fb802550e63aa61945790616f97a7Alan Viverette                throw new RuntimeException(e);
385607bd848269fb802550e63aa61945790616f97a7Alan Viverette            } finally {
386607bd848269fb802550e63aa61945790616f97a7Alan Viverette                a.recycle();
387607bd848269fb802550e63aa61945790616f97a7Alan Viverette            }
38845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
389607bd848269fb802550e63aa61945790616f97a7Alan Viverette
39045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        // Apply theme to contained color state list.
39145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mTint != null && state.mTint.canApplyTheme()) {
39245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            state.mTint.applyTheme(t);
393607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
394607bd848269fb802550e63aa61945790616f97a7Alan Viverette
395ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer path = state.mVPathRenderer;
3969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        if (path != null && path.canApplyTheme()) {
3979453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            path.applyTheme(t);
3989453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
39945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
40045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        // Update local state.
40145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
4029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
4039453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
404fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    /**
405fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension.
406fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * This is used to calculate the path animation accuracy.
407fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     *
408fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * @hide
409fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     */
410fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    public float getPixelSize() {
411f2b1cff4e2b152a7c776a7a79e8225a591f97d3eAndreas Gampe        if (mVectorState == null || mVectorState.mVPathRenderer == null ||
412fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
413fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
414fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
415fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mViewportWidth == 0) {
416fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount            return 1; // fall back to 1:1 pixel mapping.
417fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        }
418fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
419fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
420fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
421fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
422fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float scaleX = viewportWidth / intrinsicWidth;
423fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float scaleY = viewportHeight / intrinsicHeight;
424fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        return Math.min(scaleX, scaleY);
425fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    }
426fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount
4274b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    /** @hide */
4284b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    public static VectorDrawable create(Resources resources, int rid) {
4294b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        try {
430874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            final XmlPullParser parser = resources.getXml(rid);
431874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            final AttributeSet attrs = Xml.asAttributeSet(parser);
432874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            int type;
433874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            while ((type=parser.next()) != XmlPullParser.START_TAG &&
434874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                    type != XmlPullParser.END_DOCUMENT) {
435874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                // Empty loop
436874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            }
437874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            if (type != XmlPullParser.START_TAG) {
438874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                throw new XmlPullParserException("No start tag found");
439874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            }
4404b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
4414b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final VectorDrawable drawable = new VectorDrawable();
442874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            drawable.inflate(resources, parser, attrs);
4434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
4444b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            return drawable;
4454b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (XmlPullParserException e) {
4464b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
4474b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (IOException e) {
4484b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
4494b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        }
4504b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        return null;
4514b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    }
4524b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
4532af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    private static int applyAlpha(int color, float alpha) {
4542af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int alphaBytes = Color.alpha(color);
4552af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color &= 0x00FFFFFF;
4562af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
4572af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        return color;
4582af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    }
4592af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
4609cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    @Override
4619cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
4629cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            throws XmlPullParserException, IOException {
463a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VectorDrawableState state = mVectorState;
464a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
465a95c8abb366d9c39450513335f550b56da13b30aztenghui        state.mVPathRenderer = pathRenderer;
466a95c8abb366d9c39450513335f550b56da13b30aztenghui
467607bd848269fb802550e63aa61945790616f97a7Alan Viverette        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
4689cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        updateStateFromTypedArray(a);
4699cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        a.recycle();
4709cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
471a95c8abb366d9c39450513335f550b56da13b30aztenghui        state.mCacheDirty = true;
47255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        inflateInternal(res, parser, attrs, theme);
4739cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
4749cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
4759cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
4769cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
477a95c8abb366d9c39450513335f550b56da13b30aztenghui    private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
4789cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
479a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
4809cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
4818e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
4828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
4838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
4849cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        // Extract the theme attributes, if any.
4859cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
4869cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
4879cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
4889cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tintMode != -1) {
4899cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
4909cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
4919cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
4929cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
4939cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tint != null) {
4949cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTint = tint;
4959cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
496738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
497738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        state.mAutoMirrored = a.getBoolean(
498738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
499a95c8abb366d9c39450513335f550b56da13b30aztenghui
500a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mViewportWidth = a.getFloat(
501a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
502a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mViewportHeight = a.getFloat(
503a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight);
504a95c8abb366d9c39450513335f550b56da13b30aztenghui
505a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (pathRenderer.mViewportWidth <= 0) {
506a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5071c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires viewportWidth > 0");
508a95c8abb366d9c39450513335f550b56da13b30aztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
509a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5101c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires viewportHeight > 0");
511a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
512a95c8abb366d9c39450513335f550b56da13b30aztenghui
513a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mBaseWidth = a.getDimension(
514a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
515a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mBaseHeight = a.getDimension(
516a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
517a95c8abb366d9c39450513335f550b56da13b30aztenghui
518a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (pathRenderer.mBaseWidth <= 0) {
519a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5201c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires width > 0");
521a95c8abb366d9c39450513335f550b56da13b30aztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
522a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5231c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires height > 0");
524a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
5258490354dc651dd8f25036ef0dda7917fb33013edztenghui
5268490354dc651dd8f25036ef0dda7917fb33013edztenghui        final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
5278490354dc651dd8f25036ef0dda7917fb33013edztenghui                pathRenderer.getAlpha());
5288490354dc651dd8f25036ef0dda7917fb33013edztenghui        pathRenderer.setAlpha(alphaInFloat);
5298490354dc651dd8f25036ef0dda7917fb33013edztenghui
5305004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette        final String name = a.getString(R.styleable.VectorDrawable_name);
5315004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette        if (name != null) {
5325004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            pathRenderer.mRootName = name;
5335004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
5348490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
5359cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
5369cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
53755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
5388e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
5398e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final VectorDrawableState state = mVectorState;
540a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
541abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noPathTag = true;
5429453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
5434d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Use a stack to help to build the group tree.
5444d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // The top of the stack is always the current group.
5454d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
5464d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        groupStack.push(pathRenderer.mRootGroup);
547abb7d134c02ac60091108c491dafb00877093170John Hoford
548abb7d134c02ac60091108c491dafb00877093170John Hoford        int eventType = parser.getEventType();
549abb7d134c02ac60091108c491dafb00877093170John Hoford        while (eventType != XmlPullParser.END_DOCUMENT) {
550abb7d134c02ac60091108c491dafb00877093170John Hoford            if (eventType == XmlPullParser.START_TAG) {
5519453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                final String tagName = parser.getName();
5524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final VGroup currentGroup = groupStack.peek();
5534d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
554abb7d134c02ac60091108c491dafb00877093170John Hoford                if (SHAPE_PATH.equals(tagName)) {
555a95c8abb366d9c39450513335f550b56da13b30aztenghui                    final VFullPath path = new VFullPath();
5569453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    path.inflate(res, attrs, theme);
5578d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(path);
558e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (path.getPathName() != null) {
55955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
560e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
561abb7d134c02ac60091108c491dafb00877093170John Hoford                    noPathTag = false;
5628e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= path.mChangingConfigurations;
563a95c8abb366d9c39450513335f550b56da13b30aztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
564a95c8abb366d9c39450513335f550b56da13b30aztenghui                    final VClipPath path = new VClipPath();
565a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.inflate(res, attrs, theme);
566a95c8abb366d9c39450513335f550b56da13b30aztenghui                    currentGroup.mChildren.add(path);
567a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (path.getPathName() != null) {
568a95c8abb366d9c39450513335f550b56da13b30aztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
569a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
570a95c8abb366d9c39450513335f550b56da13b30aztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
5716d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
5724d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    VGroup newChildGroup = new VGroup();
5734d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    newChildGroup.inflate(res, attrs, theme);
5748d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(newChildGroup);
5754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.push(newChildGroup);
576e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (newChildGroup.getGroupName() != null) {
57755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
57855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                                newChildGroup);
579e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
5808e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
581abb7d134c02ac60091108c491dafb00877093170John Hoford                }
5824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
5834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final String tagName = parser.getName();
5844d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                if (SHAPE_GROUP.equals(tagName)) {
5854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.pop();
5864d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
587abb7d134c02ac60091108c491dafb00877093170John Hoford            }
588abb7d134c02ac60091108c491dafb00877093170John Hoford            eventType = parser.next();
589abb7d134c02ac60091108c491dafb00877093170John Hoford        }
5909453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
5914d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the tree out for debug.
5924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        if (DBG_VECTOR_DRAWABLE) {
5934d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
5946d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui        }
5956d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
596a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (noPathTag) {
5979453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final StringBuffer tag = new StringBuffer();
5989453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
599a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (tag.length() > 0) {
600a95c8abb366d9c39450513335f550b56da13b30aztenghui                tag.append(" or ");
601abb7d134c02ac60091108c491dafb00877093170John Hoford            }
602a95c8abb366d9c39450513335f550b56da13b30aztenghui            tag.append(SHAPE_PATH);
6039453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6049453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            throw new XmlPullParserException("no " + tag + " defined");
605abb7d134c02ac60091108c491dafb00877093170John Hoford        }
606abb7d134c02ac60091108c491dafb00877093170John Hoford    }
607abb7d134c02ac60091108c491dafb00877093170John Hoford
6084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
6094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        String indent = "";
6108d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < level; i++) {
6114d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            indent += "    ";
6124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
6134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the current node
6148d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
6154d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                + " rotation is " + currentGroup.mRotate);
6168d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
6178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        // Then print all the children groups
6188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
6198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            Object child = currentGroup.mChildren.get(i);
6208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (child instanceof VGroup) {
6218d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                printGroupTree((VGroup) child, level + 1);
6228d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
6234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
6244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    }
6254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
62655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
62755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public int getChangingConfigurations() {
62855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
62955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
63055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
631482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    void setAllowCaching(boolean allowCaching) {
632482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        mAllowCaching = allowCaching;
633482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    }
634482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
635738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    private boolean needMirroring() {
636738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
637738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
638738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
639738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
640738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public void setAutoMirrored(boolean mirrored) {
641738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (mVectorState.mAutoMirrored != mirrored) {
642738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            mVectorState.mAutoMirrored = mirrored;
643738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            invalidateSelf();
644738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
645738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
646738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
647738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
648738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public boolean isAutoMirrored() {
649738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return mVectorState.mAutoMirrored;
650738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
651738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
6525c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    private static class VectorDrawableState extends ConstantState {
6539cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        int[] mThemeAttrs;
6545c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        int mChangingConfigurations;
655ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        VPathRenderer mVPathRenderer;
656607bd848269fb802550e63aa61945790616f97a7Alan Viverette        ColorStateList mTint = null;
657607bd848269fb802550e63aa61945790616f97a7Alan Viverette        Mode mTintMode = DEFAULT_TINT_MODE;
658738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        boolean mAutoMirrored;
6595c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
660482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Bitmap mCachedBitmap;
661482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int[] mCachedThemeAttrs;
662482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        ColorStateList mCachedTint;
663482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Mode mCachedTintMode;
664482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int mCachedRootAlpha;
665670689af43358568bf2b5916284f1cac5762f428ztenghui        boolean mCachedAutoMirrored;
666670689af43358568bf2b5916284f1cac5762f428ztenghui        boolean mCacheDirty;
667482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
668b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        /** Temporary paint object used to draw cached bitmaps. */
669b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        Paint mTempPaint;
670b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
67155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Deep copy for mutate() or implicitly mutate.
6725c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public VectorDrawableState(VectorDrawableState copy) {
6735c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            if (copy != null) {
6749cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette                mThemeAttrs = copy.mThemeAttrs;
6755c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette                mChangingConfigurations = copy.mChangingConfigurations;
676ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
6776f6578e81c1df207da47e2e1337382341f271206Chet Haase                if (copy.mVPathRenderer.mFillPaint != null) {
6786f6578e81c1df207da47e2e1337382341f271206Chet Haase                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
6796f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
6806f6578e81c1df207da47e2e1337382341f271206Chet Haase                if (copy.mVPathRenderer.mStrokePaint != null) {
6816f6578e81c1df207da47e2e1337382341f271206Chet Haase                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
6826f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
683b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTint = copy.mTint;
684b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = copy.mTintMode;
685738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                mAutoMirrored = copy.mAutoMirrored;
6865c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            }
6875c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
6885c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
689b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) {
6908490354dc651dd8f25036ef0dda7917fb33013edztenghui            // The bitmap's size is the same as the bounds.
691b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            final Paint p = getPaint(filter);
692b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            canvas.drawBitmap(mCachedBitmap, 0, 0, p);
6938490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
6948490354dc651dd8f25036ef0dda7917fb33013edztenghui
6958490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean hasTranslucentRoot() {
6968490354dc651dd8f25036ef0dda7917fb33013edztenghui            return mVPathRenderer.getRootAlpha() < 255;
6978490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
6988490354dc651dd8f25036ef0dda7917fb33013edztenghui
6998490354dc651dd8f25036ef0dda7917fb33013edztenghui        /**
7008490354dc651dd8f25036ef0dda7917fb33013edztenghui         * @return null when there is no need for alpha paint.
7018490354dc651dd8f25036ef0dda7917fb33013edztenghui         */
702b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        public Paint getPaint(ColorFilter filter) {
703b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            if (!hasTranslucentRoot() && filter == null) {
704b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                return null;
7058490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
706b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
707b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            if (mTempPaint == null) {
708b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                mTempPaint = new Paint();
709eec6164e6f6178343219bdedcb1e26779fae7f89ztenghui                mTempPaint.setFilterBitmap(true);
710b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            }
711b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
712b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mTempPaint.setColorFilter(filter);
713b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            return mTempPaint;
7148490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
7158490354dc651dd8f25036ef0dda7917fb33013edztenghui
7168490354dc651dd8f25036ef0dda7917fb33013edztenghui        public void updateCachedBitmap(Rect bounds) {
7178490354dc651dd8f25036ef0dda7917fb33013edztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
7188490354dc651dd8f25036ef0dda7917fb33013edztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
719b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null);
7208490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
7218490354dc651dd8f25036ef0dda7917fb33013edztenghui
7228490354dc651dd8f25036ef0dda7917fb33013edztenghui        public void createCachedBitmapIfNeeded(Rect bounds) {
7238490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (mCachedBitmap == null || !canReuseBitmap(bounds.width(),
7248490354dc651dd8f25036ef0dda7917fb33013edztenghui                    bounds.height())) {
7258490354dc651dd8f25036ef0dda7917fb33013edztenghui                mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
7268490354dc651dd8f25036ef0dda7917fb33013edztenghui                        Bitmap.Config.ARGB_8888);
7279c13ed366f205d94b2f3f4ddc96b55b1b9faadbaztenghui                mCacheDirty = true;
7288490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
7298490354dc651dd8f25036ef0dda7917fb33013edztenghui
7308490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
7318490354dc651dd8f25036ef0dda7917fb33013edztenghui
7328490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean canReuseBitmap(int width, int height) {
7338490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (width == mCachedBitmap.getWidth()
7348490354dc651dd8f25036ef0dda7917fb33013edztenghui                    && height == mCachedBitmap.getHeight()) {
7358490354dc651dd8f25036ef0dda7917fb33013edztenghui                return true;
7368490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
7378490354dc651dd8f25036ef0dda7917fb33013edztenghui            return false;
7388490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
7398490354dc651dd8f25036ef0dda7917fb33013edztenghui
7408490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean canReuseCache() {
741670689af43358568bf2b5916284f1cac5762f428ztenghui            if (!mCacheDirty
742670689af43358568bf2b5916284f1cac5762f428ztenghui                    && mCachedThemeAttrs == mThemeAttrs
743482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTint == mTint
744482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTintMode == mTintMode
745670689af43358568bf2b5916284f1cac5762f428ztenghui                    && mCachedAutoMirrored == mAutoMirrored
7468490354dc651dd8f25036ef0dda7917fb33013edztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
747482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                return true;
748482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
749482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            return false;
750482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
751482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
752482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        public void updateCacheStates() {
753482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
754482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // likely hit cache miss more, but practically not much difference.
755482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedThemeAttrs = mThemeAttrs;
756482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTint = mTint;
757482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTintMode = mTintMode;
758482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
759670689af43358568bf2b5916284f1cac5762f428ztenghui            mCachedAutoMirrored = mAutoMirrored;
760670689af43358568bf2b5916284f1cac5762f428ztenghui            mCacheDirty = false;
761482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
762482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
763607bd848269fb802550e63aa61945790616f97a7Alan Viverette        @Override
764607bd848269fb802550e63aa61945790616f97a7Alan Viverette        public boolean canApplyTheme() {
76545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mThemeAttrs != null
76645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
76745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mTint != null && mTint.canApplyTheme())
768d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                    || super.canApplyTheme();
769607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
770607bd848269fb802550e63aa61945790616f97a7Alan Viverette
77155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VectorDrawableState() {
77255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVPathRenderer = new VPathRenderer();
77355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
77455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
7755c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
7765c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable() {
77717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            return new VectorDrawable(this);
7785c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
7795c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
7805c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
7815c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res) {
78217cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viverette            return new VectorDrawable(this);
7835c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
7845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
7855c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
7865c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public int getChangingConfigurations() {
7875c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return mChangingConfigurations;
7885c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
7895c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    }
7905c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
791ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui    private static class VPathRenderer {
7924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        /* Right now the internal data structure is organized as a tree.
7934d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * Each node can be a group node, or a path.
7944d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * A group node can have groups or paths as children, but a path node has
7954d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * no children.
7964d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * One example can be:
7974d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                 Root Group
7984d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                /    |     \
7994d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *           Group    Path    Group
8004d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *          /     \             |
8014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *         Path   Path         Path
8024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *
8034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         */
80455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables that only used temporarily inside the draw() call, so there
80555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // is no need for deep copying.
8066f6578e81c1df207da47e2e1337382341f271206Chet Haase        private final Path mPath;
8076f6578e81c1df207da47e2e1337382341f271206Chet Haase        private final Path mRenderPath;
80855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mFinalPathMatrix = new Matrix();
8094b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
8104b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mStrokePaint;
8114b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mFillPaint;
812abb7d134c02ac60091108c491dafb00877093170John Hoford        private PathMeasure mPathMeasure;
8134b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
81455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
81555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
8168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
81755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final VGroup mRootGroup;
818a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mBaseWidth = 0;
819a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mBaseHeight = 0;
820a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mViewportWidth = 0;
821a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mViewportHeight = 0;
8228490354dc651dd8f25036ef0dda7917fb33013edztenghui        int mRootAlpha = 0xFF;
8238490354dc651dd8f25036ef0dda7917fb33013edztenghui        String mRootName = null;
8249453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
82555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
826abb7d134c02ac60091108c491dafb00877093170John Hoford
827ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer() {
8284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mRootGroup = new VGroup();
8296f6578e81c1df207da47e2e1337382341f271206Chet Haase            mPath = new Path();
8306f6578e81c1df207da47e2e1337382341f271206Chet Haase            mRenderPath = new Path();
831abb7d134c02ac60091108c491dafb00877093170John Hoford        }
8329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
8332af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public void setRootAlpha(int alpha) {
8342af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mRootAlpha = alpha;
8352af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
8362af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
8372af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public int getRootAlpha() {
8382af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            return mRootAlpha;
8392af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
8402af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
8418490354dc651dd8f25036ef0dda7917fb33013edztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
8428490354dc651dd8f25036ef0dda7917fb33013edztenghui        // Animator like to use alpha from 0 to 1.
8438490354dc651dd8f25036ef0dda7917fb33013edztenghui        public void setAlpha(float alpha) {
8448490354dc651dd8f25036ef0dda7917fb33013edztenghui            setRootAlpha((int) (alpha * 255));
8458490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8468490354dc651dd8f25036ef0dda7917fb33013edztenghui
8478490354dc651dd8f25036ef0dda7917fb33013edztenghui        @SuppressWarnings("unused")
8488490354dc651dd8f25036ef0dda7917fb33013edztenghui        public float getAlpha() {
8498490354dc651dd8f25036ef0dda7917fb33013edztenghui            return getRootAlpha() / 255.0f;
8508490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8518490354dc651dd8f25036ef0dda7917fb33013edztenghui
852ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer(VPathRenderer copy) {
85355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
8546f6578e81c1df207da47e2e1337382341f271206Chet Haase            mPath = new Path(copy.mPath);
8556f6578e81c1df207da47e2e1337382341f271206Chet Haase            mRenderPath = new Path(copy.mRenderPath);
856abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseWidth = copy.mBaseWidth;
857abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseHeight = copy.mBaseHeight;
8585eb5cde467081d1af628e5463ba55f110265a86fztenghui            mViewportWidth = copy.mViewportWidth;
859abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportHeight = copy.mViewportHeight;
8608e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations = copy.mChangingConfigurations;
86155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootAlpha = copy.mRootAlpha;
8628490354dc651dd8f25036ef0dda7917fb33013edztenghui            mRootName = copy.mRootName;
8638490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (copy.mRootName != null) {
8648490354dc651dd8f25036ef0dda7917fb33013edztenghui                mVGTargetsMap.put(copy.mRootName, this);
8658490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
866abb7d134c02ac60091108c491dafb00877093170John Hoford        }
867abb7d134c02ac60091108c491dafb00877093170John Hoford
8689453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public boolean canApplyTheme() {
8694d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // If one of the paths can apply theme, then return true;
8704d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return recursiveCanApplyTheme(mRootGroup);
8714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
8724d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
8734d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private boolean recursiveCanApplyTheme(VGroup currentGroup) {
8744d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, if there is one path return true,
8754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // then we return true for the whole tree.
8768d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
8778d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
8788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
8798d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
8808d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
8818d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
8828d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()
8838d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            || recursiveCanApplyTheme(childGroup)) {
8848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
8858d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
8868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
8878d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
8888d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
8898d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
8908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
8914d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
8924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
8939453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            return false;
8949453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
8959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
8969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void applyTheme(Theme t) {
8974d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Apply theme to every path of the tree.
8984d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            recursiveApplyTheme(mRootGroup, t);
8994d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
9004d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
9024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, apply theme to all paths which
9034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // can apply theme.
9048d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
9058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
9068d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
9078d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
9088d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
9098d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()) {
9108d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childGroup.applyTheme(t);
9118d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
9128d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    recursiveApplyTheme(childGroup, t);
9138d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
9148d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
9158d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
9168d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childPath.applyTheme(t);
9178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
9184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
9194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
920abb7d134c02ac60091108c491dafb00877093170John Hoford        }
921abb7d134c02ac60091108c491dafb00877093170John Hoford
9224d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
923b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                Canvas canvas, int w, int h, ColorFilter filter) {
9244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Calculate current group's matrix by preConcat the parent's and
9254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // and the current one on the top of the stack.
9264d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
9274d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Mi the local matrix at level i of the group tree.
9284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
9294d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
9304d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
931054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            // Save the current clip information, which is local to this group.
932054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            canvas.save();
9338d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            // Draw the group tree in the same order as the XML file.
9348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
9358d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = currentGroup.mChildren.get(i);
9368d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
9378d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
9388d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
939b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                            canvas, w, h, filter);
9408d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
9418d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
942b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    drawPath(currentGroup, childPath, canvas, w, h, filter);
9438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
944abb7d134c02ac60091108c491dafb00877093170John Hoford            }
945054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            canvas.restore();
9464d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
947abb7d134c02ac60091108c491dafb00877093170John Hoford
948b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
9494d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Travese the tree in pre-order to draw.
950d538fa0fb21171d8256b7d800ae757757f4e3a44Andreas Gampe            drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvas, w, h, filter);
951abb7d134c02ac60091108c491dafb00877093170John Hoford        }
952abb7d134c02ac60091108c491dafb00877093170John Hoford
953b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
954b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                ColorFilter filter) {
9558490354dc651dd8f25036ef0dda7917fb33013edztenghui            final float scaleX = w / mViewportWidth;
9569d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui            final float scaleY = h / mViewportHeight;
9579d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui            final float minScale = Math.min(scaleX, scaleY);
958abb7d134c02ac60091108c491dafb00877093170John Hoford
9594d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mFinalPathMatrix.set(vGroup.mStackedMatrix);
9605a836f74df027bb568da17fbde4e641b6a56d2a9ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
961abb7d134c02ac60091108c491dafb00877093170John Hoford
9628d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            vPath.toPath(mPath);
9638d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final Path path = mPath;
964abb7d134c02ac60091108c491dafb00877093170John Hoford
9658d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.reset();
9669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
967a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (vPath.isClipPath()) {
968a95c8abb366d9c39450513335f550b56da13b30aztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
9698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                canvas.clipPath(mRenderPath, Region.Op.REPLACE);
9708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            } else {
971a95c8abb366d9c39450513335f550b56da13b30aztenghui                VFullPath fullPath = (VFullPath) vPath;
972a95c8abb366d9c39450513335f550b56da13b30aztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
973a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
974a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
975a95c8abb366d9c39450513335f550b56da13b30aztenghui
976a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (mPathMeasure == null) {
977a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure = new PathMeasure();
978a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
979a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mPathMeasure.setPath(mPath, false);
980a95c8abb366d9c39450513335f550b56da13b30aztenghui
981a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float len = mPathMeasure.getLength();
982a95c8abb366d9c39450513335f550b56da13b30aztenghui                    start = start * len;
983a95c8abb366d9c39450513335f550b56da13b30aztenghui                    end = end * len;
984a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.reset();
985a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (start > end) {
986a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(start, len, path, true);
987a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(0f, end, path, true);
988a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else {
989a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(start, end, path, true);
990a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
991a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.rLineTo(0, 0); // fix bug in measure
992a95c8abb366d9c39450513335f550b56da13b30aztenghui                }
993a95c8abb366d9c39450513335f550b56da13b30aztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
994a95c8abb366d9c39450513335f550b56da13b30aztenghui
995a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
9968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mFillPaint == null) {
9978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint = new Paint();
9988d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
9998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setAntiAlias(true);
100063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                    }
1001b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
1002b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    final Paint fillPaint = mFillPaint;
1003b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
1004b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    fillPaint.setColorFilter(filter);
1005b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    canvas.drawPath(mRenderPath, fillPaint);
10068d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
100763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1008a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
10098d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mStrokePaint == null) {
10108d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint = new Paint();
10118d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
10128d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setAntiAlias(true);
10138d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
10144b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
10158d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    final Paint strokePaint = mStrokePaint;
1016a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (fullPath.mStrokeLineJoin != null) {
1017a95c8abb366d9c39450513335f550b56da13b30aztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
10188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
1019abb7d134c02ac60091108c491dafb00877093170John Hoford
1020a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (fullPath.mStrokeLineCap != null) {
1021a95c8abb366d9c39450513335f550b56da13b30aztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
10228d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
102363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1024c4d651ec8a8c190c5df173166357c2fdf47472ceztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
1025b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
1026b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    strokePaint.setColorFilter(filter);
1027a95c8abb366d9c39450513335f550b56da13b30aztenghui                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale);
10288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
102963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                }
1030abb7d134c02ac60091108c491dafb00877093170John Hoford            }
1031abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1032abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1033abb7d134c02ac60091108c491dafb00877093170John Hoford
1034a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VGroup {
103555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
103655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // the parents' local matrices with the current one.
103755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mStackedMatrix = new Matrix();
103855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
103955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
104055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
10418d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
1042abb7d134c02ac60091108c491dafb00877093170John Hoford
104363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mRotate = 0;
104463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotX = 0;
104563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotY = 0;
1046452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleX = 1;
1047452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleY = 1;
1048452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateX = 0;
1049452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateY = 0;
10504d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
105155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mLocalMatrix is updated based on the update of transformation information,
105255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // either parsed from the XML or by animation.
10534d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private final Matrix mLocalMatrix = new Matrix();
10548e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
105563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private int[] mThemeAttrs;
1056e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        private String mGroupName = null;
1057e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
105855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
105955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRotate = copy.mRotate;
106055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotX = copy.mPivotX;
106155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotY = copy.mPivotY;
106255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleX = copy.mScaleX;
106355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleY = copy.mScaleY;
106455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateX = copy.mTranslateX;
106555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateY = copy.mTranslateY;
106655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
106755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupName = copy.mGroupName;
106855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
106955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mGroupName != null) {
107055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                targetsMap.put(mGroupName, this);
107155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
107255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
107355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mLocalMatrix.set(copy.mLocalMatrix);
107455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
10758d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = copy.mChildren;
10768d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
10778d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object copyChild = children.get(i);
10788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (copyChild instanceof VGroup) {
10798d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup copyGroup = (VGroup) copyChild;
10808d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
1081a95c8abb366d9c39450513335f550b56da13b30aztenghui                } else {
1082a95c8abb366d9c39450513335f550b56da13b30aztenghui                    VPath newPath = null;
1083a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (copyChild instanceof VFullPath) {
1084a95c8abb366d9c39450513335f550b56da13b30aztenghui                        newPath = new VFullPath((VFullPath) copyChild);
1085a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else if (copyChild instanceof VClipPath) {
1086a95c8abb366d9c39450513335f550b56da13b30aztenghui                        newPath = new VClipPath((VClipPath) copyChild);
1087a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else {
1088a95c8abb366d9c39450513335f550b56da13b30aztenghui                        throw new IllegalStateException("Unknown object in the tree!");
1089a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
10908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(newPath);
10918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (newPath.mPathName != null) {
10928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        targetsMap.put(newPath.mPathName, newPath);
10938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
109455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                }
109555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
109655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
109755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
109855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup() {
109955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
110055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
1101a95c8abb366d9c39450513335f550b56da13b30aztenghui        public String getGroupName() {
1102a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mGroupName;
1103a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1104a95c8abb366d9c39450513335f550b56da13b30aztenghui
1105a95c8abb366d9c39450513335f550b56da13b30aztenghui        public Matrix getLocalMatrix() {
1106a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mLocalMatrix;
1107a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1108a95c8abb366d9c39450513335f550b56da13b30aztenghui
1109a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
1110a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(res, theme, attrs,
1111a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawableGroup);
1112a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1113a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1114a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1115a95c8abb366d9c39450513335f550b56da13b30aztenghui
1116a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1117a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1118a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1119a95c8abb366d9c39450513335f550b56da13b30aztenghui
1120a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Extract the theme attributes, if any.
1121a95c8abb366d9c39450513335f550b56da13b30aztenghui            mThemeAttrs = a.extractThemeAttrs();
1122a95c8abb366d9c39450513335f550b56da13b30aztenghui
1123a95c8abb366d9c39450513335f550b56da13b30aztenghui            mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
1124a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
1125a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
1126a95c8abb366d9c39450513335f550b56da13b30aztenghui            mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
1127a95c8abb366d9c39450513335f550b56da13b30aztenghui            mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
1128a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
1129a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
1130a95c8abb366d9c39450513335f550b56da13b30aztenghui
1131a95c8abb366d9c39450513335f550b56da13b30aztenghui            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
1132a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (groupName != null) {
1133a95c8abb366d9c39450513335f550b56da13b30aztenghui                mGroupName = groupName;
1134a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1135a95c8abb366d9c39450513335f550b56da13b30aztenghui
1136a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateLocalMatrix();
1137a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1138a95c8abb366d9c39450513335f550b56da13b30aztenghui
1139607bd848269fb802550e63aa61945790616f97a7Alan Viverette        public boolean canApplyTheme() {
1140607bd848269fb802550e63aa61945790616f97a7Alan Viverette            return mThemeAttrs != null;
1141607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
1142607bd848269fb802550e63aa61945790616f97a7Alan Viverette
1143a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1144a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mThemeAttrs == null) {
1145a95c8abb366d9c39450513335f550b56da13b30aztenghui                return;
1146a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1147a95c8abb366d9c39450513335f550b56da13b30aztenghui
1148607bd848269fb802550e63aa61945790616f97a7Alan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawableGroup);
1149a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1150a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1151a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1152a95c8abb366d9c39450513335f550b56da13b30aztenghui
1153a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateLocalMatrix() {
1154a95c8abb366d9c39450513335f550b56da13b30aztenghui            // The order we apply is the same as the
1155a95c8abb366d9c39450513335f550b56da13b30aztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
1156a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.reset();
1157a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
1158a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
1159a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
1160a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
1161a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1162a95c8abb366d9c39450513335f550b56da13b30aztenghui
1163a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1164a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1165e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getRotation() {
1166e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mRotate;
1167e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1168e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1169a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1170e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setRotation(float rotation) {
1171e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (rotation != mRotate) {
1172e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mRotate = rotation;
1173e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1174e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1175e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1176e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1177a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1178e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotX() {
1179e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotX;
1180e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1181e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1182a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1183e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotX(float pivotX) {
1184e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotX != mPivotX) {
1185e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotX = pivotX;
1186e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1187e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1188e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1189e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1190a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1191e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotY() {
1192e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotY;
1193e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1194e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1195a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1196e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotY(float pivotY) {
1197e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotY != mPivotY) {
1198e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotY = pivotY;
1199e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1200e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1201e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1202e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1203a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1204e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleX() {
1205e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleX;
1206e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
12074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1208a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1209e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleX(float scaleX) {
1210e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleX != mScaleX) {
1211e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleX = scaleX;
1212e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1213e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1214e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1215e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1216a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1217e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleY() {
1218e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleY;
1219e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1220e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1221a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1222e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleY(float scaleY) {
1223e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleY != mScaleY) {
1224e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleY = scaleY;
1225e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1226e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1227e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1228e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1229a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1230e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateX() {
1231e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateX;
1232e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1233e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1234a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1235e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateX(float translateX) {
1236e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateX != mTranslateX) {
1237e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateX = translateX;
1238e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1239e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1240e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1241e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1242a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1243e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateY() {
1244e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateY;
1245e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1246e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1247a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1248e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateY(float translateY) {
1249e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateY != mTranslateY) {
1250e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateY = translateY;
1251e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1252e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1253e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1254a95c8abb366d9c39450513335f550b56da13b30aztenghui    }
1255e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1256a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1257a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Common Path information for clip path and normal path.
1258a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
1259a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VPath {
1260a95c8abb366d9c39450513335f550b56da13b30aztenghui        protected PathParser.PathDataNode[] mNodes = null;
1261a95c8abb366d9c39450513335f550b56da13b30aztenghui        String mPathName;
1262a95c8abb366d9c39450513335f550b56da13b30aztenghui        int mChangingConfigurations;
1263a95c8abb366d9c39450513335f550b56da13b30aztenghui
1264a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VPath() {
1265a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Empty constructor.
12664d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
12674d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1268a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VPath(VPath copy) {
1269a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPathName = copy.mPathName;
1270a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations = copy.mChangingConfigurations;
1271a95c8abb366d9c39450513335f550b56da13b30aztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
12724d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
12734d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1274a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void toPath(Path path) {
1275a95c8abb366d9c39450513335f550b56da13b30aztenghui            path.reset();
1276a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mNodes != null) {
1277a95c8abb366d9c39450513335f550b56da13b30aztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
1278a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
12794d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
12804d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1281a95c8abb366d9c39450513335f550b56da13b30aztenghui        public String getPathName() {
1282a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mPathName;
12838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
12848e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
1285a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean canApplyTheme() {
1286a95c8abb366d9c39450513335f550b56da13b30aztenghui            return false;
1287a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
128863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1289a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1290a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
129163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1292a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean isClipPath() {
1293a95c8abb366d9c39450513335f550b56da13b30aztenghui            return false;
1294a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
129563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1296a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1297a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1298a95c8abb366d9c39450513335f550b56da13b30aztenghui        public PathParser.PathDataNode[] getPathData() {
1299a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mNodes;
1300a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1301a95c8abb366d9c39450513335f550b56da13b30aztenghui
1302a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1303a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
1304a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
1305a95c8abb366d9c39450513335f550b56da13b30aztenghui                // This should not happen in the middle of animation.
1306a95c8abb366d9c39450513335f550b56da13b30aztenghui                mNodes = PathParser.deepCopyNodes(nodes);
1307a95c8abb366d9c39450513335f550b56da13b30aztenghui            } else {
1308a95c8abb366d9c39450513335f550b56da13b30aztenghui                PathParser.updateNodes(mNodes, nodes);
130963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            }
1310a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1311a95c8abb366d9c39450513335f550b56da13b30aztenghui    }
131263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1313a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1314a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Clip path, which only has name and pathData.
1315a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
13168490354dc651dd8f25036ef0dda7917fb33013edztenghui    private static class VClipPath extends VPath {
1317a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VClipPath() {
1318a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Empty constructor.
13198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
13204d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1321a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VClipPath(VClipPath copy) {
1322a95c8abb366d9c39450513335f550b56da13b30aztenghui            super(copy);
1323a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
13244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1325a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
1326a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1327a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawableClipPath);
13288e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
132963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
133063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        }
133163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1332a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1333a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1334a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1335a95c8abb366d9c39450513335f550b56da13b30aztenghui
13365004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name);
13375004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathName != null) {
13385004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mPathName = pathName;
13395004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
13405004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette
13415004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData);
13425004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathData != null) {
13435004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mNodes = PathParser.createNodesFromPathData(pathData);
13445004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
1345a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1346a95c8abb366d9c39450513335f550b56da13b30aztenghui
1347a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1348a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean isClipPath() {
1349a95c8abb366d9c39450513335f550b56da13b30aztenghui            return true;
13504d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
1351abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1352abb7d134c02ac60091108c491dafb00877093170John Hoford
1353a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1354a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Normal path, which contains all the fill / paint information.
1355a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
1356a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VFullPath extends VPath {
135755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
135855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
13599453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private int[] mThemeAttrs;
13609453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1361a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui        int mStrokeColor = Color.TRANSPARENT;
1362abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeWidth = 0;
13632e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
1364a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui        int mFillColor = Color.TRANSPARENT;
13652e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        float mStrokeAlpha = 1.0f;
1366abb7d134c02ac60091108c491dafb00877093170John Hoford        int mFillRule;
13672e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        float mFillAlpha = 1.0f;
1368abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathStart = 0;
1369abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathEnd = 1;
1370abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathOffset = 0;
13719453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
13724b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
13734b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
1374abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeMiterlimit = 4;
13759453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1376a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VFullPath() {
13779453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            // Empty constructor.
13789453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
13799453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1380a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VFullPath(VFullPath copy) {
1381a95c8abb366d9c39450513335f550b56da13b30aztenghui            super(copy);
138255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
138355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
138455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeColor = copy.mStrokeColor;
138555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeWidth = copy.mStrokeWidth;
13862e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = copy.mStrokeAlpha;
138755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillColor = copy.mFillColor;
138855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillRule = copy.mFillRule;
13892e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = copy.mFillAlpha;
139055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathStart = copy.mTrimPathStart;
139155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathEnd = copy.mTrimPathEnd;
139255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathOffset = copy.mTrimPathOffset;
139355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
139455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineCap = copy.mStrokeLineCap;
139555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
139655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
1397abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1398abb7d134c02ac60091108c491dafb00877093170John Hoford
13997f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
14007f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
14017f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_BUTT:
14027f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.BUTT;
14037f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_ROUND:
14047f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.ROUND;
14057f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_SQUARE:
14067f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.SQUARE;
14077f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
14087f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
14097f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
14107f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
14117f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
14127f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
14137f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
14147f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_MITER:
14157f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.MITER;
14167f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_ROUND:
14177f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.ROUND;
14187f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_BEVEL:
14197f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.BEVEL;
14207f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
14217f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
14227f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
14237f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
14247f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
1425a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1426a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean canApplyTheme() {
1427a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mThemeAttrs != null;
1428eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1429eb034fbca40006c55db143047eb628c4b657730aztenghui
1430a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
1431a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1432a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath);
1433a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1434a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1435a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1436a95c8abb366d9c39450513335f550b56da13b30aztenghui
1437a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1438a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1439a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1440a95c8abb366d9c39450513335f550b56da13b30aztenghui
1441a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Extract the theme attributes, if any.
1442a95c8abb366d9c39450513335f550b56da13b30aztenghui            mThemeAttrs = a.extractThemeAttrs();
1443a95c8abb366d9c39450513335f550b56da13b30aztenghui
14445004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathName = a.getString(R.styleable.VectorDrawablePath_name);
14455004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathName != null) {
14465004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mPathName = pathName;
14475004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
14485004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette
14495004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData);
14505004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathData != null) {
14515004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mNodes = PathParser.createNodesFromPathData(pathData);
14525004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
1453a95c8abb366d9c39450513335f550b56da13b30aztenghui
1454a95c8abb366d9c39450513335f550b56da13b30aztenghui            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
1455a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mFillColor);
14562e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
14572e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui                    mFillAlpha);
1458a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeLineCap = getStrokeLineCap(a.getInt(
1459a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
1460a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
1461a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
1462a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeMiterlimit = a.getFloat(
1463a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
1464a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
1465a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mStrokeColor);
14662e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
14672e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui                    mStrokeAlpha);
1468a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
1469a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mStrokeWidth);
1470a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
1471a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mTrimPathEnd);
1472a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathOffset = a.getFloat(
1473a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
1474a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathStart = a.getFloat(
1475a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
1476a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1477a95c8abb366d9c39450513335f550b56da13b30aztenghui
1478a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1479a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1480a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mThemeAttrs == null) {
1481a95c8abb366d9c39450513335f550b56da13b30aztenghui                return;
1482a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1483a95c8abb366d9c39450513335f550b56da13b30aztenghui
1484607bd848269fb802550e63aa61945790616f97a7Alan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
1485a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1486a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1487a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1488a95c8abb366d9c39450513335f550b56da13b30aztenghui
1489a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1490eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1491dbcccffc3760f702887faa95b2748125bac88a89ztenghui        int getStrokeColor() {
1492e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeColor;
1493e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1494e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1495eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1496dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setStrokeColor(int strokeColor) {
1497e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeColor = strokeColor;
1498e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1499e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1500eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1501e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeWidth() {
1502e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeWidth;
1503e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1504e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1505eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1506e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeWidth(float strokeWidth) {
1507e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeWidth = strokeWidth;
1508e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1509e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1510eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1511dbcccffc3760f702887faa95b2748125bac88a89ztenghui        float getStrokeAlpha() {
15122e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            return mStrokeAlpha;
15132e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
15142e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
15152e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1516dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setStrokeAlpha(float strokeAlpha) {
15172e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = strokeAlpha;
15182e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
15192e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
15202e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1521dbcccffc3760f702887faa95b2748125bac88a89ztenghui        int getFillColor() {
1522e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillColor;
1523e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1524e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1525eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1526dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setFillColor(int fillColor) {
1527e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillColor = fillColor;
1528e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1529e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1530eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1531dbcccffc3760f702887faa95b2748125bac88a89ztenghui        float getFillAlpha() {
15322e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            return mFillAlpha;
15332e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
15342e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
15352e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1536dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setFillAlpha(float fillAlpha) {
15372e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = fillAlpha;
15382e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
15392e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
15402e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1541e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathStart() {
1542e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathStart;
1543e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1544e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1545eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1546e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathStart(float trimPathStart) {
1547e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathStart = trimPathStart;
1548e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1549e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1550eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1551e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathEnd() {
1552e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathEnd;
1553e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1554e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1555eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1556e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathEnd(float trimPathEnd) {
1557e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathEnd = trimPathEnd;
1558e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1559e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1560eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1561e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathOffset() {
1562e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathOffset;
1563e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1564e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1565eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1566e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathOffset(float trimPathOffset) {
1567e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathOffset = trimPathOffset;
1568e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1569abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1570abb7d134c02ac60091108c491dafb00877093170John Hoford}
1571