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;
1895080637db69ffa4f31f18f32878ddd2457e6857ztenghuiimport android.annotation.Nullable;
19b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList;
20abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources;
21abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources.Theme;
224b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viveretteimport android.content.res.TypedArray;
23482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghuiimport android.graphics.Bitmap;
24abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Canvas;
252af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghuiimport android.graphics.Color;
26abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.ColorFilter;
2787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets;
28abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Matrix;
29abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Paint;
30abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Path;
31abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PathMeasure;
32abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PixelFormat;
33b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuffColorFilter;
34abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Rect;
35b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
36e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.ArrayMap;
37abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.AttributeSet;
3895080637db69ffa4f31f18f32878ddd2457e6857ztenghuiimport android.util.DisplayMetrics;
39738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghuiimport android.util.LayoutDirection;
40abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.Log;
419af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghuiimport android.util.MathUtils;
42cf4832f69c8786b098ce18c24319021f8cd6733aztenghuiimport android.util.PathParser;
434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport android.util.Xml;
44abb7d134c02ac60091108c491dafb00877093170John Hoford
45abb7d134c02ac60091108c491dafb00877093170John Hofordimport com.android.internal.R;
46abb7d134c02ac60091108c491dafb00877093170John Hoford
47abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParser;
48abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParserException;
49abb7d134c02ac60091108c491dafb00877093170John Hoford
50abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.io.IOException;
51abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.util.ArrayList;
524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghuiimport java.util.Stack;
534b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
54abb7d134c02ac60091108c491dafb00877093170John Hoford/**
556beeb75723cec42603b47664bce794a2b97d7bacChet Haase * This lets you create a drawable based on an XML vector graphic. It can be
56d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * defined in an XML file with the <code>&lt;vector></code> element.
57abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
5846e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * The vector drawable has the following elements:
59abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
60177dffd869ff1f5bdf816faead01a7dc4980bf75ztenghui * <dt><code>&lt;vector></code></dt>
61a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
620ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define a vector drawable
63a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
64c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt>
65c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of this vector drawable.</dd>
66a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:width</code></dt>
670ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the intrinsic width of the drawable.
68a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd>
69a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:height</code></dt>
700ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the intrinsic height the drawable.
71a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd>
72a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportWidth</code></dt>
730ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the width of the viewport space. Viewport is basically
74a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd>
75a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportHeight</code></dt>
760ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the height of the viewport space. Viewport is basically
77a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd>
78a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tint</code></dt>
79a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
80a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tintMode</code></dt>
81a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd>
82a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:autoMirrored</code></dt>
83a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
84a95c8abb366d9c39450513335f550b56da13b30aztenghui * RTL (right-to-left).</dd>
85c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:alpha</code></dt>
86c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>The opacity of this drawable.</dd>
87a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
88a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
89a95c8abb366d9c39450513335f550b56da13b30aztenghui *
90a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
916d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dt><code>&lt;group></code></dt>
92452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>Defines a group of paths or subgroups, plus transformation information.
93452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * The transformations are defined in the same coordinates as the viewport.
94a95c8abb366d9c39450513335f550b56da13b30aztenghui * And the transformations are applied in the order of scale, rotate then translate.
95a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
96c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt>
97c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of the group.</dd>
98a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:rotation</code></dt>
99a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The degrees of rotation of the group.</dd>
100a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pivotX</code></dt>
101a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The X 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:pivotY</code></dt>
104a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
105a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
106a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleX</code></dt>
107a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the X Coordinate.</dd>
108a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleY</code></dt>
109a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the Y coordinate.</dd>
110a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateX</code></dt>
111a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the X coordinate.
112a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
113a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateY</code></dt>
114a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the Y coordinate.
115a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd>
116a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
117a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
118a95c8abb366d9c39450513335f550b56da13b30aztenghui *
119a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
120abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;path></code></dt>
1216d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dd>Defines paths to be drawn.
122abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
123a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt>
124a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the path.</dd>
125a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt>
1260ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Defines path data using exactly same format as "d" attribute
127a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data. This is defined in the viewport space.</dd>
128a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:fillColor</code></dt>
129a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui * <dd>Defines the color to fill the path (none if not present).</dd>
130a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeColor</code></dt>
131d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Defines the color to draw the path outline (none if not present).</dd>
132a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeWidth</code></dt>
133a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The width a path stroke.</dd>
1342e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:strokeAlpha</code></dt>
1352e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity of a path stroke.</dd>
1362e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:fillAlpha</code></dt>
1372e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity to fill the path with.</dd>
138a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathStart</code></dt>
139a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd>
140a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathEnd</code></dt>
141a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd>
142a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathOffset</code></dt>
143a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Shift trim region (allows showed region to include the start and end), in the range
144a95c8abb366d9c39450513335f550b56da13b30aztenghui * from 0 to 1.</dd>
145a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineCap</code></dt>
146a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the linecap for a stroked path: butt, round, square.</dd>
147a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineJoin</code></dt>
148a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd>
149a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeMiterLimit</code></dt>
150a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the Miter limit for a stroked path.</dd>
151a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
152a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl>
153a95c8abb366d9c39450513335f550b56da13b30aztenghui *
154a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
155a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>&lt;clip-path></code></dt>
1566fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * <dd>Defines path to be the current clip. Note that the clip path only apply to
1576fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * the current group and its children.
158a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl>
159a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt>
160a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the clip path.</dd>
161a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt>
1620ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Defines clip path using the same format as "d" attribute
163a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data.</dd>
164a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd>
165abb7d134c02ac60091108c491dafb00877093170John Hoford * </dl>
166a95c8abb366d9c39450513335f550b56da13b30aztenghui * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
167a95c8abb366d9c39450513335f550b56da13b30aztenghui * <pre>
168a95c8abb366d9c39450513335f550b56da13b30aztenghui * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android";
169a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:height=&quot;64dp&quot;
170a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:width=&quot;64dp&quot;
171a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportHeight=&quot;600&quot;
172a95c8abb366d9c39450513335f550b56da13b30aztenghui *     android:viewportWidth=&quot;600&quot; &gt;
173a95c8abb366d9c39450513335f550b56da13b30aztenghui *     &lt;group
174a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:name=&quot;rotationGroup&quot;
175a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:pivotX=&quot;300.0&quot;
176a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:pivotY=&quot;300.0&quot;
177a95c8abb366d9c39450513335f550b56da13b30aztenghui *         android:rotation=&quot;45.0&quot; &gt;
178a95c8abb366d9c39450513335f550b56da13b30aztenghui *         &lt;path
179a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:name=&quot;v&quot;
180a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:fillColor=&quot;#000000&quot;
181a95c8abb366d9c39450513335f550b56da13b30aztenghui *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
182a95c8abb366d9c39450513335f550b56da13b30aztenghui *     &lt;/group&gt;
183a95c8abb366d9c39450513335f550b56da13b30aztenghui * &lt;/vector&gt;
184a95c8abb366d9c39450513335f550b56da13b30aztenghui * </pre></li>
185abb7d134c02ac60091108c491dafb00877093170John Hoford */
186a95c8abb366d9c39450513335f550b56da13b30aztenghui
187abb7d134c02ac60091108c491dafb00877093170John Hofordpublic class VectorDrawable extends Drawable {
1889453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private static final String LOGTAG = VectorDrawable.class.getSimpleName();
1899453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
190a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static final String SHAPE_CLIP_PATH = "clip-path";
1916d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui    private static final String SHAPE_GROUP = "group";
192abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_PATH = "path";
193abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VECTOR = "vector";
194abb7d134c02ac60091108c491dafb00877093170John Hoford
195abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_BUTT = 0;
196abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_ROUND = 1;
197abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_SQUARE = 2;
1989453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
199abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_MITER = 0;
200abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_ROUND = 1;
201abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_BEVEL = 2;
2029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
20335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    // Cap the bitmap size, such that it won't hurt the performance too much
20435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    // and it won't crash due to a very large scale.
20535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    // The drawable will look blurry above this size.
20635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    private static final int MAX_CACHED_BITMAP_SIZE = 2048;
20735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui
2084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private static final boolean DBG_VECTOR_DRAWABLE = false;
2094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
21055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private VectorDrawableState mVectorState;
211e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
212b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    private PorterDuffColorFilter mTintFilter;
213b07b086bd42181f62718a6394b56be3917b12511Alan Viverette    private ColorFilter mColorFilter;
214b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
21555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private boolean mMutated;
21655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
217482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
218482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // caching the bitmap by default is allowed.
219482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    private boolean mAllowCaching = true;
220482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
22195080637db69ffa4f31f18f32878ddd2457e6857ztenghui    // Given the virtual display setup, the dpi can be different than the inflation's dpi.
22295080637db69ffa4f31f18f32878ddd2457e6857ztenghui    // Therefore, we need to scale the values we got from the getDimension*().
22395080637db69ffa4f31f18f32878ddd2457e6857ztenghui    private int mDpiScaledWidth = 0;
22495080637db69ffa4f31f18f32878ddd2457e6857ztenghui    private int mDpiScaledHeight = 0;
22595080637db69ffa4f31f18f32878ddd2457e6857ztenghui    private Insets mDpiScaleInsets = Insets.NONE;
22695080637db69ffa4f31f18f32878ddd2457e6857ztenghui
22735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    // Temp variable, only for saving "new" operation at the draw() time.
22835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    private final float[] mTmpFloats = new float[9];
22935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    private final Matrix mTmpMatrix = new Matrix();
23035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui    private final Rect mTmpBounds = new Rect();
23135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui
232abb7d134c02ac60091108c491dafb00877093170John Hoford    public VectorDrawable() {
23395080637db69ffa4f31f18f32878ddd2457e6857ztenghui        this(null, null);
234abb7d134c02ac60091108c491dafb00877093170John Hoford    }
235abb7d134c02ac60091108c491dafb00877093170John Hoford
23695080637db69ffa4f31f18f32878ddd2457e6857ztenghui    private VectorDrawable(@NonNull VectorDrawableState state, @Nullable Resources res) {
23795080637db69ffa4f31f18f32878ddd2457e6857ztenghui        if (state == null) {
23895080637db69ffa4f31f18f32878ddd2457e6857ztenghui            mVectorState = new VectorDrawableState();
23995080637db69ffa4f31f18f32878ddd2457e6857ztenghui        } else {
24095080637db69ffa4f31f18f32878ddd2457e6857ztenghui            mVectorState = state;
24195080637db69ffa4f31f18f32878ddd2457e6857ztenghui            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
24295080637db69ffa4f31f18f32878ddd2457e6857ztenghui        }
24395080637db69ffa4f31f18f32878ddd2457e6857ztenghui        updateDimensionInfo(res, false);
244abb7d134c02ac60091108c491dafb00877093170John Hoford    }
245abb7d134c02ac60091108c491dafb00877093170John Hoford
24655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
24755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public Drawable mutate() {
24855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        if (!mMutated && super.mutate() == this) {
24955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVectorState = new VectorDrawableState(mVectorState);
25055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mMutated = true;
25155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
25255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return this;
25355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
25455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
255727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    /**
256727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     * @hide
257727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette     */
258727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    public void clearMutated() {
259727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        super.clearMutated();
260727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette        mMutated = false;
261727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette    }
262727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette
263e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    Object getTargetByName(String name) {
26455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
265e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
266e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
267abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
268abb7d134c02ac60091108c491dafb00877093170John Hoford    public ConstantState getConstantState() {
26955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
27055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState;
271abb7d134c02ac60091108c491dafb00877093170John Hoford    }
272abb7d134c02ac60091108c491dafb00877093170John Hoford
2734554a6a5137d8e9bdfb623ad84ff344a48b7eb9dAlan Viverette    @Override
274abb7d134c02ac60091108c491dafb00877093170John Hoford    public void draw(Canvas canvas) {
27535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // We will offset the bounds for drawBitmap, so copyBounds() here instead
27635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // of getBounds().
27735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        copyBounds(mTmpBounds);
27835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
27934c623cbf3677820c4170f24c5211f663dda91f7ztenghui            // Nothing to draw
2801968201b44567262e7b2e382eee3d88990748d89Dan Sandler            return;
2811968201b44567262e7b2e382eee3d88990748d89Dan Sandler        }
2821968201b44567262e7b2e382eee3d88990748d89Dan Sandler
28335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // Color filters always override tint filters.
28435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
28535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui
28635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // The imageView can scale the canvas in different ways, in order to
28735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
28835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // size first. This bitmap size is determined by the bounds and the
28935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // canvas scale.
29035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        canvas.getMatrix(mTmpMatrix);
29135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        mTmpMatrix.getValues(mTmpFloats);
29235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
29335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
29435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
29535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
29635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
29735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
29835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui
29935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        if (scaledWidth <= 0 || scaledHeight <= 0) {
30035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            return;
30135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        }
30235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui
3030670f029a4e59448aa53b46a98e60dff6404f360ztenghui        final int saveCount = canvas.save();
30435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        canvas.translate(mTmpBounds.left, mTmpBounds.top);
305738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
30635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // Handle RTL mirroring.
30735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        final boolean needMirroring = needMirroring();
308738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (needMirroring) {
30935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            canvas.translate(mTmpBounds.width(), 0);
310738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            canvas.scale(-1.0f, 1.0f);
311738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
312482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
31335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // At this point, canvas has been translated to the right position.
31435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // And we use this bound for the destination rect for the drawBitmap, so
31535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        // we offset to (0, 0);
31635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        mTmpBounds.offsetTo(0, 0);
317b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
31835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
319482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        if (!mAllowCaching) {
32035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
321482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        } else {
3228490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (!mVectorState.canReuseCache()) {
32335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
324482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                mVectorState.updateCacheStates();
325482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
326482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
32735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
3284b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.restoreToCount(saveCount);
329abb7d134c02ac60091108c491dafb00877093170John Hoford    }
330abb7d134c02ac60091108c491dafb00877093170John Hoford
331abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getAlpha() {
333e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
334e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
335e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
336e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
337abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setAlpha(int alpha) {
3382af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
3392af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
340abb7d134c02ac60091108c491dafb00877093170John Hoford            invalidateSelf();
341abb7d134c02ac60091108c491dafb00877093170John Hoford        }
342abb7d134c02ac60091108c491dafb00877093170John Hoford    }
343abb7d134c02ac60091108c491dafb00877093170John Hoford
344abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
345abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setColorFilter(ColorFilter colorFilter) {
346b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        mColorFilter = colorFilter;
347fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        invalidateSelf();
348abb7d134c02ac60091108c491dafb00877093170John Hoford    }
349abb7d134c02ac60091108c491dafb00877093170John Hoford
350abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
351a74171190077d5ef8704a29442669e806447d560Alan Viverette    public ColorFilter getColorFilter() {
352a74171190077d5ef8704a29442669e806447d560Alan Viverette        return mColorFilter;
353a74171190077d5ef8704a29442669e806447d560Alan Viverette    }
354a74171190077d5ef8704a29442669e806447d560Alan Viverette
355a74171190077d5ef8704a29442669e806447d560Alan Viverette    @Override
356a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintList(ColorStateList tint) {
357b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
358a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (state.mTint != tint) {
359b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTint = tint;
360a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
361a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            invalidateSelf();
362a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        }
363a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    }
364b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
365a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    @Override
366a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette    public void setTintMode(Mode tintMode) {
367a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        final VectorDrawableState state = mVectorState;
368a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette        if (state.mTintMode != tintMode) {
369a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            state.mTintMode = tintMode;
370a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
371b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            invalidateSelf();
372b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
373b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
374b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
375b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
376607bd848269fb802550e63aa61945790616f97a7Alan Viverette    public boolean isStateful() {
377607bd848269fb802550e63aa61945790616f97a7Alan Viverette        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
378607bd848269fb802550e63aa61945790616f97a7Alan Viverette                && mVectorState.mTint.isStateful());
379607bd848269fb802550e63aa61945790616f97a7Alan Viverette    }
380607bd848269fb802550e63aa61945790616f97a7Alan Viverette
381607bd848269fb802550e63aa61945790616f97a7Alan Viverette    @Override
382b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    protected boolean onStateChange(int[] stateSet) {
383b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
384b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != null && state.mTintMode != null) {
385b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
386607bd848269fb802550e63aa61945790616f97a7Alan Viverette            invalidateSelf();
387b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            return true;
388b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
389b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        return false;
390b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
391b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
392b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
393abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getOpacity() {
394abb7d134c02ac60091108c491dafb00877093170John Hoford        return PixelFormat.TRANSLUCENT;
395abb7d134c02ac60091108c491dafb00877093170John Hoford    }
396abb7d134c02ac60091108c491dafb00877093170John Hoford
397abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
398abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicWidth() {
39995080637db69ffa4f31f18f32878ddd2457e6857ztenghui        return mDpiScaledWidth;
400abb7d134c02ac60091108c491dafb00877093170John Hoford    }
401abb7d134c02ac60091108c491dafb00877093170John Hoford
402abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
403abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicHeight() {
40495080637db69ffa4f31f18f32878ddd2457e6857ztenghui        return mDpiScaledHeight;
405abb7d134c02ac60091108c491dafb00877093170John Hoford    }
406abb7d134c02ac60091108c491dafb00877093170John Hoford
40787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    /** @hide */
40887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    @Override
40987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    public Insets getOpticalInsets() {
41095080637db69ffa4f31f18f32878ddd2457e6857ztenghui        return mDpiScaleInsets;
41195080637db69ffa4f31f18f32878ddd2457e6857ztenghui    }
41295080637db69ffa4f31f18f32878ddd2457e6857ztenghui
41395080637db69ffa4f31f18f32878ddd2457e6857ztenghui    /*
41495080637db69ffa4f31f18f32878ddd2457e6857ztenghui     * Update the VectorDrawable dimension since the res can be in different Dpi now.
41595080637db69ffa4f31f18f32878ddd2457e6857ztenghui     * Basically, when a new instance is created or getDimension() is called, we should update
41695080637db69ffa4f31f18f32878ddd2457e6857ztenghui     * the current VectorDrawable's dimension information.
41795080637db69ffa4f31f18f32878ddd2457e6857ztenghui     * Only after updateStateFromTypedArray() is called, we should called this and update the
41895080637db69ffa4f31f18f32878ddd2457e6857ztenghui     * constant state's dpi info, i.e. updateConstantStateDensity == true.
41995080637db69ffa4f31f18f32878ddd2457e6857ztenghui     */
42095080637db69ffa4f31f18f32878ddd2457e6857ztenghui    void updateDimensionInfo(@Nullable Resources res, boolean updateConstantStateDensity) {
42195080637db69ffa4f31f18f32878ddd2457e6857ztenghui        if (res != null) {
42295080637db69ffa4f31f18f32878ddd2457e6857ztenghui            final int densityDpi = res.getDisplayMetrics().densityDpi;
42395080637db69ffa4f31f18f32878ddd2457e6857ztenghui            final int targetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi;
42495080637db69ffa4f31f18f32878ddd2457e6857ztenghui
42595080637db69ffa4f31f18f32878ddd2457e6857ztenghui            if (updateConstantStateDensity) {
42695080637db69ffa4f31f18f32878ddd2457e6857ztenghui                mVectorState.mVPathRenderer.mTargetDensity = targetDensity;
42795080637db69ffa4f31f18f32878ddd2457e6857ztenghui            } else {
42895080637db69ffa4f31f18f32878ddd2457e6857ztenghui                final int constantStateDensity = mVectorState.mVPathRenderer.mTargetDensity;
42995080637db69ffa4f31f18f32878ddd2457e6857ztenghui                if (targetDensity != constantStateDensity && constantStateDensity != 0) {
43095080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    mDpiScaledWidth = Bitmap.scaleFromDensity(
43195080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            (int) mVectorState.mVPathRenderer.mBaseWidth, constantStateDensity,
43295080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
43395080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    mDpiScaledHeight = Bitmap.scaleFromDensity(
43495080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            (int) mVectorState.mVPathRenderer.mBaseHeight,constantStateDensity,
43595080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
43695080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    final int left = Bitmap.scaleFromDensity(
43795080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            mVectorState.mVPathRenderer.mOpticalInsets.left, constantStateDensity,
43895080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
43995080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    final int right = Bitmap.scaleFromDensity(
44095080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            mVectorState.mVPathRenderer.mOpticalInsets.right, constantStateDensity,
44195080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
44295080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    final int top = Bitmap.scaleFromDensity(
44395080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            mVectorState.mVPathRenderer.mOpticalInsets.top, constantStateDensity,
44495080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
44595080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    final int bottom = Bitmap.scaleFromDensity(
44695080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            mVectorState.mVPathRenderer.mOpticalInsets.bottom, constantStateDensity,
44795080637db69ffa4f31f18f32878ddd2457e6857ztenghui                            targetDensity);
44895080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    mDpiScaleInsets = Insets.of(left, top, right, bottom);
44995080637db69ffa4f31f18f32878ddd2457e6857ztenghui                    return;
45095080637db69ffa4f31f18f32878ddd2457e6857ztenghui                }
45195080637db69ffa4f31f18f32878ddd2457e6857ztenghui            }
45295080637db69ffa4f31f18f32878ddd2457e6857ztenghui        }
45395080637db69ffa4f31f18f32878ddd2457e6857ztenghui        // For all the other cases, like either res is null, constant state is not initialized or
45495080637db69ffa4f31f18f32878ddd2457e6857ztenghui        // target density is the same as the constant state, we will just use the constant state
45595080637db69ffa4f31f18f32878ddd2457e6857ztenghui        // dimensions.
45695080637db69ffa4f31f18f32878ddd2457e6857ztenghui        mDpiScaledWidth = (int) mVectorState.mVPathRenderer.mBaseWidth;
45795080637db69ffa4f31f18f32878ddd2457e6857ztenghui        mDpiScaledHeight = (int) mVectorState.mVPathRenderer.mBaseHeight;
45895080637db69ffa4f31f18f32878ddd2457e6857ztenghui        mDpiScaleInsets = mVectorState.mVPathRenderer.mOpticalInsets;
45987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette    }
46087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
461abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
4629453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public boolean canApplyTheme() {
463d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette        return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme();
4649453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
4659453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
4669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    @Override
4679453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public void applyTheme(Theme t) {
4689453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        super.applyTheme(t);
4699453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
4709453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        final VectorDrawableState state = mVectorState;
47145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state == null) {
47245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return;
47345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
47445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
47545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mThemeAttrs != null) {
47645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            final TypedArray a = t.resolveAttributes(
47745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    state.mThemeAttrs, R.styleable.VectorDrawable);
478607bd848269fb802550e63aa61945790616f97a7Alan Viverette            try {
479607bd848269fb802550e63aa61945790616f97a7Alan Viverette                state.mCacheDirty = true;
480607bd848269fb802550e63aa61945790616f97a7Alan Viverette                updateStateFromTypedArray(a);
48195080637db69ffa4f31f18f32878ddd2457e6857ztenghui                updateDimensionInfo(t.getResources(), true /* update constant state */);
482607bd848269fb802550e63aa61945790616f97a7Alan Viverette            } catch (XmlPullParserException e) {
483607bd848269fb802550e63aa61945790616f97a7Alan Viverette                throw new RuntimeException(e);
484607bd848269fb802550e63aa61945790616f97a7Alan Viverette            } finally {
485607bd848269fb802550e63aa61945790616f97a7Alan Viverette                a.recycle();
486607bd848269fb802550e63aa61945790616f97a7Alan Viverette            }
48745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        }
488607bd848269fb802550e63aa61945790616f97a7Alan Viverette
48945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        // Apply theme to contained color state list.
49045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        if (state.mTint != null && state.mTint.canApplyTheme()) {
491e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            state.mTint = state.mTint.obtainForTheme(t);
492607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
493607bd848269fb802550e63aa61945790616f97a7Alan Viverette
494ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer path = state.mVPathRenderer;
4959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        if (path != null && path.canApplyTheme()) {
4969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            path.applyTheme(t);
4979453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
49845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette
49945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        // Update local state.
50045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
5019453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
5029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
503fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    /**
504fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension.
505fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * This is used to calculate the path animation accuracy.
506fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     *
507fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     * @hide
508fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount     */
509fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    public float getPixelSize() {
510f2b1cff4e2b152a7c776a7a79e8225a591f97d3eAndreas Gampe        if (mVectorState == null || mVectorState.mVPathRenderer == null ||
511fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
512fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
513fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
514fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount                mVectorState.mVPathRenderer.mViewportWidth == 0) {
515fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount            return 1; // fall back to 1:1 pixel mapping.
516fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        }
517fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
518fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
519fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
520fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
521fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float scaleX = viewportWidth / intrinsicWidth;
522fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        float scaleY = viewportHeight / intrinsicHeight;
523fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount        return Math.min(scaleX, scaleY);
524fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount    }
525fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount
5264b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    /** @hide */
5274b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    public static VectorDrawable create(Resources resources, int rid) {
5284b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        try {
529874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            final XmlPullParser parser = resources.getXml(rid);
530874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            final AttributeSet attrs = Xml.asAttributeSet(parser);
531874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            int type;
532874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            while ((type=parser.next()) != XmlPullParser.START_TAG &&
533874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                    type != XmlPullParser.END_DOCUMENT) {
534874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                // Empty loop
535874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            }
536874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            if (type != XmlPullParser.START_TAG) {
537874bcd82c223ce58c9d76edcf619b3988c672307ztenghui                throw new XmlPullParserException("No start tag found");
538874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            }
5394b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
5404b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final VectorDrawable drawable = new VectorDrawable();
541874bcd82c223ce58c9d76edcf619b3988c672307ztenghui            drawable.inflate(resources, parser, attrs);
5424b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
5434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            return drawable;
5444b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (XmlPullParserException e) {
5454b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
5464b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (IOException e) {
5474b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
5484b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        }
5494b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        return null;
5504b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    }
5514b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
5522af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    private static int applyAlpha(int color, float alpha) {
5532af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int alphaBytes = Color.alpha(color);
5542af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color &= 0x00FFFFFF;
5552af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
5562af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        return color;
5572af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    }
5582af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
5599cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    @Override
5609cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
5619cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            throws XmlPullParserException, IOException {
562a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VectorDrawableState state = mVectorState;
563a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
564a95c8abb366d9c39450513335f550b56da13b30aztenghui        state.mVPathRenderer = pathRenderer;
565a95c8abb366d9c39450513335f550b56da13b30aztenghui
566607bd848269fb802550e63aa61945790616f97a7Alan Viverette        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
5679cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        updateStateFromTypedArray(a);
5689cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        a.recycle();
5699cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
570a95c8abb366d9c39450513335f550b56da13b30aztenghui        state.mCacheDirty = true;
57155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        inflateInternal(res, parser, attrs, theme);
5729cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
5739cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
57495080637db69ffa4f31f18f32878ddd2457e6857ztenghui        updateDimensionInfo(res, true /* update constant state */);
5759cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
5769cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
577a95c8abb366d9c39450513335f550b56da13b30aztenghui    private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
5789cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
579a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
5809cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
5818e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
5828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
5838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
5849cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        // Extract the theme attributes, if any.
5859cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
5869cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
5879cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
5889cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tintMode != -1) {
5899cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
5909cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
5919cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
5929cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
5939cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tint != null) {
5949cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTint = tint;
5959cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
596738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
597738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        state.mAutoMirrored = a.getBoolean(
598738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
599a95c8abb366d9c39450513335f550b56da13b30aztenghui
600a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mViewportWidth = a.getFloat(
601a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth);
602a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mViewportHeight = a.getFloat(
603a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight);
604a95c8abb366d9c39450513335f550b56da13b30aztenghui
605a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (pathRenderer.mViewportWidth <= 0) {
606a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6071c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires viewportWidth > 0");
608a95c8abb366d9c39450513335f550b56da13b30aztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
609a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6101c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires viewportHeight > 0");
611a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
612a95c8abb366d9c39450513335f550b56da13b30aztenghui
613a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mBaseWidth = a.getDimension(
614a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth);
615a95c8abb366d9c39450513335f550b56da13b30aztenghui        pathRenderer.mBaseHeight = a.getDimension(
616a95c8abb366d9c39450513335f550b56da13b30aztenghui                R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight);
617a95c8abb366d9c39450513335f550b56da13b30aztenghui
618a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (pathRenderer.mBaseWidth <= 0) {
619a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6201c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires width > 0");
621a95c8abb366d9c39450513335f550b56da13b30aztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
622a95c8abb366d9c39450513335f550b56da13b30aztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6231c4d8b2173bf4b5bbac94748959752599775628dztenghui                    "<vector> tag requires height > 0");
624a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
6258490354dc651dd8f25036ef0dda7917fb33013edztenghui
62687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetLeft = a.getDimensionPixelSize(
62787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.VectorDrawable_opticalInsetLeft, pathRenderer.mOpticalInsets.left);
62887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetTop = a.getDimensionPixelSize(
62987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.VectorDrawable_opticalInsetTop, pathRenderer.mOpticalInsets.top);
63087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetRight = a.getDimensionPixelSize(
63187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.VectorDrawable_opticalInsetRight, pathRenderer.mOpticalInsets.right);
63287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        final int insetBottom = a.getDimensionPixelSize(
63387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette                R.styleable.VectorDrawable_opticalInsetBottom, pathRenderer.mOpticalInsets.bottom);
63487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        pathRenderer.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom);
63587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette
6368490354dc651dd8f25036ef0dda7917fb33013edztenghui        final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha,
6378490354dc651dd8f25036ef0dda7917fb33013edztenghui                pathRenderer.getAlpha());
6388490354dc651dd8f25036ef0dda7917fb33013edztenghui        pathRenderer.setAlpha(alphaInFloat);
6398490354dc651dd8f25036ef0dda7917fb33013edztenghui
6405004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette        final String name = a.getString(R.styleable.VectorDrawable_name);
6415004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette        if (name != null) {
6425004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            pathRenderer.mRootName = name;
6435004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
6448490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
6459cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
6469cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
64755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
6488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
6498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final VectorDrawableState state = mVectorState;
650a95c8abb366d9c39450513335f550b56da13b30aztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
651abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noPathTag = true;
6529453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6534d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Use a stack to help to build the group tree.
6544d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // The top of the stack is always the current group.
6554d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
6564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        groupStack.push(pathRenderer.mRootGroup);
657abb7d134c02ac60091108c491dafb00877093170John Hoford
658abb7d134c02ac60091108c491dafb00877093170John Hoford        int eventType = parser.getEventType();
659abb7d134c02ac60091108c491dafb00877093170John Hoford        while (eventType != XmlPullParser.END_DOCUMENT) {
660abb7d134c02ac60091108c491dafb00877093170John Hoford            if (eventType == XmlPullParser.START_TAG) {
6619453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                final String tagName = parser.getName();
6624d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final VGroup currentGroup = groupStack.peek();
6634d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
664abb7d134c02ac60091108c491dafb00877093170John Hoford                if (SHAPE_PATH.equals(tagName)) {
665a95c8abb366d9c39450513335f550b56da13b30aztenghui                    final VFullPath path = new VFullPath();
6669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    path.inflate(res, attrs, theme);
6678d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(path);
668e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (path.getPathName() != null) {
66955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
670e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
671abb7d134c02ac60091108c491dafb00877093170John Hoford                    noPathTag = false;
6728e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= path.mChangingConfigurations;
673a95c8abb366d9c39450513335f550b56da13b30aztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
674a95c8abb366d9c39450513335f550b56da13b30aztenghui                    final VClipPath path = new VClipPath();
675a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.inflate(res, attrs, theme);
676a95c8abb366d9c39450513335f550b56da13b30aztenghui                    currentGroup.mChildren.add(path);
677a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (path.getPathName() != null) {
678a95c8abb366d9c39450513335f550b56da13b30aztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
679a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
680a95c8abb366d9c39450513335f550b56da13b30aztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
6816d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
6824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    VGroup newChildGroup = new VGroup();
6834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    newChildGroup.inflate(res, attrs, theme);
6848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(newChildGroup);
6854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.push(newChildGroup);
686e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (newChildGroup.getGroupName() != null) {
68755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
68855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                                newChildGroup);
689e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
6908e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
691abb7d134c02ac60091108c491dafb00877093170John Hoford                }
6924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
6934d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final String tagName = parser.getName();
6944d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                if (SHAPE_GROUP.equals(tagName)) {
6954d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.pop();
6964d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
697abb7d134c02ac60091108c491dafb00877093170John Hoford            }
698abb7d134c02ac60091108c491dafb00877093170John Hoford            eventType = parser.next();
699abb7d134c02ac60091108c491dafb00877093170John Hoford        }
7009453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
7014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the tree out for debug.
7024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        if (DBG_VECTOR_DRAWABLE) {
7034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
7046d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui        }
7056d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
706a95c8abb366d9c39450513335f550b56da13b30aztenghui        if (noPathTag) {
7079453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final StringBuffer tag = new StringBuffer();
7089453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
709a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (tag.length() > 0) {
710a95c8abb366d9c39450513335f550b56da13b30aztenghui                tag.append(" or ");
711abb7d134c02ac60091108c491dafb00877093170John Hoford            }
712a95c8abb366d9c39450513335f550b56da13b30aztenghui            tag.append(SHAPE_PATH);
7139453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
7149453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            throw new XmlPullParserException("no " + tag + " defined");
715abb7d134c02ac60091108c491dafb00877093170John Hoford        }
716abb7d134c02ac60091108c491dafb00877093170John Hoford    }
717abb7d134c02ac60091108c491dafb00877093170John Hoford
7184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
7194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        String indent = "";
7208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < level; i++) {
7214d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            indent += "    ";
7224d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
7234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the current node
7248d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
7254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                + " rotation is " + currentGroup.mRotate);
7268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
7278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        // Then print all the children groups
7288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
7298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            Object child = currentGroup.mChildren.get(i);
7308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (child instanceof VGroup) {
7318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                printGroupTree((VGroup) child, level + 1);
7328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
7334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
7344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    }
7354d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
73655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
73755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public int getChangingConfigurations() {
738e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
73955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
74055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
741482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    void setAllowCaching(boolean allowCaching) {
742482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        mAllowCaching = allowCaching;
743482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    }
744482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
745738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    private boolean needMirroring() {
746738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
747738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
748738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
749738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
750738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public void setAutoMirrored(boolean mirrored) {
751738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (mVectorState.mAutoMirrored != mirrored) {
752738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            mVectorState.mAutoMirrored = mirrored;
753738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            invalidateSelf();
754738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
755738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
756738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
757738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
758738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public boolean isAutoMirrored() {
759738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return mVectorState.mAutoMirrored;
760738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
761738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
7625c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    private static class VectorDrawableState extends ConstantState {
7639cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        int[] mThemeAttrs;
7645c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        int mChangingConfigurations;
765ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        VPathRenderer mVPathRenderer;
766607bd848269fb802550e63aa61945790616f97a7Alan Viverette        ColorStateList mTint = null;
767607bd848269fb802550e63aa61945790616f97a7Alan Viverette        Mode mTintMode = DEFAULT_TINT_MODE;
768738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        boolean mAutoMirrored;
7695c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
770482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Bitmap mCachedBitmap;
771482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int[] mCachedThemeAttrs;
772482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        ColorStateList mCachedTint;
773482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Mode mCachedTintMode;
774482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int mCachedRootAlpha;
775670689af43358568bf2b5916284f1cac5762f428ztenghui        boolean mCachedAutoMirrored;
776670689af43358568bf2b5916284f1cac5762f428ztenghui        boolean mCacheDirty;
777b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        /** Temporary paint object used to draw cached bitmaps. */
778b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        Paint mTempPaint;
779b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
78055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Deep copy for mutate() or implicitly mutate.
7815c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public VectorDrawableState(VectorDrawableState copy) {
7825c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            if (copy != null) {
7839cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette                mThemeAttrs = copy.mThemeAttrs;
7845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette                mChangingConfigurations = copy.mChangingConfigurations;
785ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
7866f6578e81c1df207da47e2e1337382341f271206Chet Haase                if (copy.mVPathRenderer.mFillPaint != null) {
7876f6578e81c1df207da47e2e1337382341f271206Chet Haase                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
7886f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
7896f6578e81c1df207da47e2e1337382341f271206Chet Haase                if (copy.mVPathRenderer.mStrokePaint != null) {
7906f6578e81c1df207da47e2e1337382341f271206Chet Haase                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
7916f6578e81c1df207da47e2e1337382341f271206Chet Haase                }
792b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTint = copy.mTint;
793b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = copy.mTintMode;
794738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                mAutoMirrored = copy.mAutoMirrored;
7955c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            }
7965c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
7975c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
79835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
79935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui                Rect originalBounds) {
8008490354dc651dd8f25036ef0dda7917fb33013edztenghui            // The bitmap's size is the same as the bounds.
801b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            final Paint p = getPaint(filter);
80235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
8038490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8048490354dc651dd8f25036ef0dda7917fb33013edztenghui
8058490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean hasTranslucentRoot() {
8068490354dc651dd8f25036ef0dda7917fb33013edztenghui            return mVPathRenderer.getRootAlpha() < 255;
8078490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8088490354dc651dd8f25036ef0dda7917fb33013edztenghui
8098490354dc651dd8f25036ef0dda7917fb33013edztenghui        /**
8108490354dc651dd8f25036ef0dda7917fb33013edztenghui         * @return null when there is no need for alpha paint.
8118490354dc651dd8f25036ef0dda7917fb33013edztenghui         */
812b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        public Paint getPaint(ColorFilter filter) {
813b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            if (!hasTranslucentRoot() && filter == null) {
814b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                return null;
8158490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
816b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
817b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            if (mTempPaint == null) {
818b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                mTempPaint = new Paint();
819eec6164e6f6178343219bdedcb1e26779fae7f89ztenghui                mTempPaint.setFilterBitmap(true);
820b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            }
821b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
822b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            mTempPaint.setColorFilter(filter);
823b07b086bd42181f62718a6394b56be3917b12511Alan Viverette            return mTempPaint;
8248490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8258490354dc651dd8f25036ef0dda7917fb33013edztenghui
82635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        public void updateCachedBitmap(int width, int height) {
8278490354dc651dd8f25036ef0dda7917fb33013edztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
8288490354dc651dd8f25036ef0dda7917fb33013edztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
82935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            mVPathRenderer.draw(tmpCanvas, width, height, null);
8308490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8318490354dc651dd8f25036ef0dda7917fb33013edztenghui
83235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui        public void createCachedBitmapIfNeeded(int width, int height) {
83335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
83435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui                mCachedBitmap = Bitmap.createBitmap(width, height,
8358490354dc651dd8f25036ef0dda7917fb33013edztenghui                        Bitmap.Config.ARGB_8888);
8369c13ed366f205d94b2f3f4ddc96b55b1b9faadbaztenghui                mCacheDirty = true;
8378490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
8388490354dc651dd8f25036ef0dda7917fb33013edztenghui
8398490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8408490354dc651dd8f25036ef0dda7917fb33013edztenghui
8418490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean canReuseBitmap(int width, int height) {
8428490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (width == mCachedBitmap.getWidth()
8438490354dc651dd8f25036ef0dda7917fb33013edztenghui                    && height == mCachedBitmap.getHeight()) {
8448490354dc651dd8f25036ef0dda7917fb33013edztenghui                return true;
8458490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
8468490354dc651dd8f25036ef0dda7917fb33013edztenghui            return false;
8478490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
8488490354dc651dd8f25036ef0dda7917fb33013edztenghui
8498490354dc651dd8f25036ef0dda7917fb33013edztenghui        public boolean canReuseCache() {
850670689af43358568bf2b5916284f1cac5762f428ztenghui            if (!mCacheDirty
851670689af43358568bf2b5916284f1cac5762f428ztenghui                    && mCachedThemeAttrs == mThemeAttrs
852482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTint == mTint
853482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTintMode == mTintMode
854670689af43358568bf2b5916284f1cac5762f428ztenghui                    && mCachedAutoMirrored == mAutoMirrored
8558490354dc651dd8f25036ef0dda7917fb33013edztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
856482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                return true;
857482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
858482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            return false;
859482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
860482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
861482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        public void updateCacheStates() {
862482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
863482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // likely hit cache miss more, but practically not much difference.
864482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedThemeAttrs = mThemeAttrs;
865482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTint = mTint;
866482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTintMode = mTintMode;
867482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
868670689af43358568bf2b5916284f1cac5762f428ztenghui            mCachedAutoMirrored = mAutoMirrored;
869670689af43358568bf2b5916284f1cac5762f428ztenghui            mCacheDirty = false;
870482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
871482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
872607bd848269fb802550e63aa61945790616f97a7Alan Viverette        @Override
873607bd848269fb802550e63aa61945790616f97a7Alan Viverette        public boolean canApplyTheme() {
87445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette            return mThemeAttrs != null
87545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
87645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette                    || (mTint != null && mTint.canApplyTheme())
877d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette                    || super.canApplyTheme();
878607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
879607bd848269fb802550e63aa61945790616f97a7Alan Viverette
88055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VectorDrawableState() {
88155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVPathRenderer = new VPathRenderer();
88255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
88355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
8845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
8855c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable() {
88695080637db69ffa4f31f18f32878ddd2457e6857ztenghui            return new VectorDrawable(this, null);
8875c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
8885c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
8895c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
8905c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res) {
89195080637db69ffa4f31f18f32878ddd2457e6857ztenghui            return new VectorDrawable(this, res);
8925c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
8935c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
8945c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
8955c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public int getChangingConfigurations() {
896e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette            return mChangingConfigurations
897e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette                    | (mTint != null ? mTint.getChangingConfigurations() : 0);
8985c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
8995c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    }
9005c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
901ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui    private static class VPathRenderer {
9024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        /* Right now the internal data structure is organized as a tree.
9034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * Each node can be a group node, or a path.
9044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * A group node can have groups or paths as children, but a path node has
9054d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * no children.
9064d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * One example can be:
9074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                 Root Group
9084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                /    |     \
9094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *           Group    Path    Group
9104d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *          /     \             |
9114d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *         Path   Path         Path
9124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *
9134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         */
91455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables that only used temporarily inside the draw() call, so there
91555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // is no need for deep copying.
9166f6578e81c1df207da47e2e1337382341f271206Chet Haase        private final Path mPath;
9176f6578e81c1df207da47e2e1337382341f271206Chet Haase        private final Path mRenderPath;
91855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mFinalPathMatrix = new Matrix();
9194b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
9204b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mStrokePaint;
9214b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mFillPaint;
922abb7d134c02ac60091108c491dafb00877093170John Hoford        private PathMeasure mPathMeasure;
9234b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
92455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
92555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
9268e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
92755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final VGroup mRootGroup;
928a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mBaseWidth = 0;
929a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mBaseHeight = 0;
930a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mViewportWidth = 0;
931a95c8abb366d9c39450513335f550b56da13b30aztenghui        float mViewportHeight = 0;
93287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette        Insets mOpticalInsets = Insets.NONE;
9338490354dc651dd8f25036ef0dda7917fb33013edztenghui        int mRootAlpha = 0xFF;
9348490354dc651dd8f25036ef0dda7917fb33013edztenghui        String mRootName = null;
9359453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
93695080637db69ffa4f31f18f32878ddd2457e6857ztenghui        int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
93795080637db69ffa4f31f18f32878ddd2457e6857ztenghui
93855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
939abb7d134c02ac60091108c491dafb00877093170John Hoford
940ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer() {
9414d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mRootGroup = new VGroup();
9426f6578e81c1df207da47e2e1337382341f271206Chet Haase            mPath = new Path();
9436f6578e81c1df207da47e2e1337382341f271206Chet Haase            mRenderPath = new Path();
944abb7d134c02ac60091108c491dafb00877093170John Hoford        }
9459453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
9462af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public void setRootAlpha(int alpha) {
9472af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mRootAlpha = alpha;
9482af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
9492af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
9502af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public int getRootAlpha() {
9512af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            return mRootAlpha;
9522af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
9532af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
9548490354dc651dd8f25036ef0dda7917fb33013edztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
9558490354dc651dd8f25036ef0dda7917fb33013edztenghui        // Animator like to use alpha from 0 to 1.
9568490354dc651dd8f25036ef0dda7917fb33013edztenghui        public void setAlpha(float alpha) {
9578490354dc651dd8f25036ef0dda7917fb33013edztenghui            setRootAlpha((int) (alpha * 255));
9588490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
9598490354dc651dd8f25036ef0dda7917fb33013edztenghui
9608490354dc651dd8f25036ef0dda7917fb33013edztenghui        @SuppressWarnings("unused")
9618490354dc651dd8f25036ef0dda7917fb33013edztenghui        public float getAlpha() {
9628490354dc651dd8f25036ef0dda7917fb33013edztenghui            return getRootAlpha() / 255.0f;
9638490354dc651dd8f25036ef0dda7917fb33013edztenghui        }
9648490354dc651dd8f25036ef0dda7917fb33013edztenghui
965ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer(VPathRenderer copy) {
96655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
9676f6578e81c1df207da47e2e1337382341f271206Chet Haase            mPath = new Path(copy.mPath);
9686f6578e81c1df207da47e2e1337382341f271206Chet Haase            mRenderPath = new Path(copy.mRenderPath);
969abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseWidth = copy.mBaseWidth;
970abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseHeight = copy.mBaseHeight;
9715eb5cde467081d1af628e5463ba55f110265a86fztenghui            mViewportWidth = copy.mViewportWidth;
972abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportHeight = copy.mViewportHeight;
97387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette            mOpticalInsets = copy.mOpticalInsets;
9748e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations = copy.mChangingConfigurations;
97555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootAlpha = copy.mRootAlpha;
9768490354dc651dd8f25036ef0dda7917fb33013edztenghui            mRootName = copy.mRootName;
97795080637db69ffa4f31f18f32878ddd2457e6857ztenghui            mTargetDensity = copy.mTargetDensity;
9788490354dc651dd8f25036ef0dda7917fb33013edztenghui            if (copy.mRootName != null) {
9798490354dc651dd8f25036ef0dda7917fb33013edztenghui                mVGTargetsMap.put(copy.mRootName, this);
9808490354dc651dd8f25036ef0dda7917fb33013edztenghui            }
981abb7d134c02ac60091108c491dafb00877093170John Hoford        }
982abb7d134c02ac60091108c491dafb00877093170John Hoford
9839453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public boolean canApplyTheme() {
9844d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // If one of the paths can apply theme, then return true;
9854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return recursiveCanApplyTheme(mRootGroup);
9864d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
9874d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9884d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private boolean recursiveCanApplyTheme(VGroup currentGroup) {
9894d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, if there is one path return true,
9904d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // then we return true for the whole tree.
9918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
9928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
9938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
9948d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
9958d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
9968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
9978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()
9988d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            || recursiveCanApplyTheme(childGroup)) {
9998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
10008d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
10018d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
10028d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
10038d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
10048d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
10058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
10064d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
10074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
10089453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            return false;
10099453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
10109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
10119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void applyTheme(Theme t) {
10124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Apply theme to every path of the tree.
10134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            recursiveApplyTheme(mRootGroup, t);
10144d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
10154d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10164d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
10174d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, apply theme to all paths which
10184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // can apply theme.
10198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
10208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
10218d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
10228d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
10238d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
10248d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()) {
10258d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childGroup.applyTheme(t);
10268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
10278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    recursiveApplyTheme(childGroup, t);
10288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
10298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
10308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
10318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childPath.applyTheme(t);
10328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
10334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
10344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
1035abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1036abb7d134c02ac60091108c491dafb00877093170John Hoford
10374d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
1038b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                Canvas canvas, int w, int h, ColorFilter filter) {
10394d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Calculate current group's matrix by preConcat the parent's and
10404d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // and the current one on the top of the stack.
10414d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
10424d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Mi the local matrix at level i of the group tree.
10434d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
10444d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
10454d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1046054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            // Save the current clip information, which is local to this group.
1047054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            canvas.save();
10488d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            // Draw the group tree in the same order as the XML file.
10498d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
10508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = currentGroup.mChildren.get(i);
10518d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
10528d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
10538d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
1054b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                            canvas, w, h, filter);
10558d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
10568d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
1057b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    drawPath(currentGroup, childPath, canvas, w, h, filter);
10588d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
1059abb7d134c02ac60091108c491dafb00877093170John Hoford            }
1060054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui            canvas.restore();
10614d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
1062abb7d134c02ac60091108c491dafb00877093170John Hoford
1063b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
10644d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Travese the tree in pre-order to draw.
1065d538fa0fb21171d8256b7d800ae757757f4e3a44Andreas Gampe            drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvas, w, h, filter);
1066abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1067abb7d134c02ac60091108c491dafb00877093170John Hoford
1068b07b086bd42181f62718a6394b56be3917b12511Alan Viverette        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
1069b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                ColorFilter filter) {
10708490354dc651dd8f25036ef0dda7917fb33013edztenghui            final float scaleX = w / mViewportWidth;
10719d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui            final float scaleY = h / mViewportHeight;
10729d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui            final float minScale = Math.min(scaleX, scaleY);
10739af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
1074abb7d134c02ac60091108c491dafb00877093170John Hoford
10759af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            mFinalPathMatrix.set(groupStackedMatrix);
10765a836f74df027bb568da17fbde4e641b6a56d2a9ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
1077abb7d134c02ac60091108c491dafb00877093170John Hoford
10789af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            final float matrixScale = getMatrixScale(groupStackedMatrix);
10799af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            if (matrixScale == 0) {
10809af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                // When either x or y is scaled to 0, we don't need to draw anything.
10819af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                return;
10829af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            }
10838d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            vPath.toPath(mPath);
10848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final Path path = mPath;
1085abb7d134c02ac60091108c491dafb00877093170John Hoford
10868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.reset();
10879453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1088a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (vPath.isClipPath()) {
1089a95c8abb366d9c39450513335f550b56da13b30aztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
1090e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik                canvas.clipPath(mRenderPath);
10918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            } else {
1092a95c8abb366d9c39450513335f550b56da13b30aztenghui                VFullPath fullPath = (VFullPath) vPath;
1093a95c8abb366d9c39450513335f550b56da13b30aztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
1094a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
1095a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
1096a95c8abb366d9c39450513335f550b56da13b30aztenghui
1097a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (mPathMeasure == null) {
1098a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure = new PathMeasure();
1099a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
1100a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mPathMeasure.setPath(mPath, false);
1101a95c8abb366d9c39450513335f550b56da13b30aztenghui
1102a95c8abb366d9c39450513335f550b56da13b30aztenghui                    float len = mPathMeasure.getLength();
1103a95c8abb366d9c39450513335f550b56da13b30aztenghui                    start = start * len;
1104a95c8abb366d9c39450513335f550b56da13b30aztenghui                    end = end * len;
1105a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.reset();
1106a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (start > end) {
1107a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(start, len, path, true);
1108a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(0f, end, path, true);
1109a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else {
1110a95c8abb366d9c39450513335f550b56da13b30aztenghui                        mPathMeasure.getSegment(start, end, path, true);
1111a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
1112a95c8abb366d9c39450513335f550b56da13b30aztenghui                    path.rLineTo(0, 0); // fix bug in measure
1113a95c8abb366d9c39450513335f550b56da13b30aztenghui                }
1114a95c8abb366d9c39450513335f550b56da13b30aztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
1115a95c8abb366d9c39450513335f550b56da13b30aztenghui
1116a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
11178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mFillPaint == null) {
11188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint = new Paint();
11198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
11208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setAntiAlias(true);
112163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                    }
1122b07b086bd42181f62718a6394b56be3917b12511Alan Viverette
1123b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    final Paint fillPaint = mFillPaint;
1124b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
1125b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    fillPaint.setColorFilter(filter);
1126b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    canvas.drawPath(mRenderPath, fillPaint);
11278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
112863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1129a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
11308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mStrokePaint == null) {
11318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint = new Paint();
11328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
11338d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setAntiAlias(true);
11348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
11354b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
11368d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    final Paint strokePaint = mStrokePaint;
1137a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (fullPath.mStrokeLineJoin != null) {
1138a95c8abb366d9c39450513335f550b56da13b30aztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
11398d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
1140abb7d134c02ac60091108c491dafb00877093170John Hoford
1141a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (fullPath.mStrokeLineCap != null) {
1142a95c8abb366d9c39450513335f550b56da13b30aztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
11438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
114463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1145c4d651ec8a8c190c5df173166357c2fdf47472ceztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
1146b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
1147b07b086bd42181f62718a6394b56be3917b12511Alan Viverette                    strokePaint.setColorFilter(filter);
11489af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                    final float finalStrokeScale = minScale * matrixScale;
11499af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
11508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
115163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                }
1152abb7d134c02ac60091108c491dafb00877093170John Hoford            }
1153abb7d134c02ac60091108c491dafb00877093170John Hoford        }
11549af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui
11559af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui        private float getMatrixScale(Matrix groupStackedMatrix) {
11569af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // Given unit vectors A = (0, 1) and B = (1, 0).
11579af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
11589af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
11599af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
11609af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
11619af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            //
11629af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
11639af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // scale on x and y axis, and take the minimal of these two.
11649af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // For skew case, an unit square will mapped to a parallelogram. And this function will
11659af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            // return the minimal height of the 2 bases.
11669af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float[] unitVectors = new float[] {0, 1, 1, 0};
11679af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            groupStackedMatrix.mapVectors(unitVectors);
11689af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
11699af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
11709af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
11719af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                    unitVectors[2], unitVectors[3]);
11729af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float maxScale = MathUtils.max(scaleX, scaleY);
11739af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui
11749af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            float matrixScale = 0;
11759af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            if (maxScale > 0) {
11769af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                matrixScale = MathUtils.abs(crossProduct) / maxScale;
11779af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            }
11789af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            if (DBG_VECTOR_DRAWABLE) {
11799af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
11809af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            }
11819af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui            return matrixScale;
11829af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui        }
1183abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1184abb7d134c02ac60091108c491dafb00877093170John Hoford
1185a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VGroup {
118655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
118755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // the parents' local matrices with the current one.
118855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mStackedMatrix = new Matrix();
118955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
119055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
119155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
11928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
1193abb7d134c02ac60091108c491dafb00877093170John Hoford
119463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mRotate = 0;
119563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotX = 0;
119663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotY = 0;
1197452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleX = 1;
1198452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleY = 1;
1199452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateX = 0;
1200452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateY = 0;
12014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
120255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mLocalMatrix is updated based on the update of transformation information,
120355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // either parsed from the XML or by animation.
12044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private final Matrix mLocalMatrix = new Matrix();
12058e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
120663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private int[] mThemeAttrs;
1207e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        private String mGroupName = null;
1208e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
120955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
121055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRotate = copy.mRotate;
121155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotX = copy.mPivotX;
121255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotY = copy.mPivotY;
121355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleX = copy.mScaleX;
121455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleY = copy.mScaleY;
121555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateX = copy.mTranslateX;
121655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateY = copy.mTranslateY;
121755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
121855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupName = copy.mGroupName;
121955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
122055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mGroupName != null) {
122155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                targetsMap.put(mGroupName, this);
122255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
122355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
122455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mLocalMatrix.set(copy.mLocalMatrix);
122555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
12268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = copy.mChildren;
12278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
12288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object copyChild = children.get(i);
12298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (copyChild instanceof VGroup) {
12308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup copyGroup = (VGroup) copyChild;
12318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
1232a95c8abb366d9c39450513335f550b56da13b30aztenghui                } else {
1233a95c8abb366d9c39450513335f550b56da13b30aztenghui                    VPath newPath = null;
1234a95c8abb366d9c39450513335f550b56da13b30aztenghui                    if (copyChild instanceof VFullPath) {
1235a95c8abb366d9c39450513335f550b56da13b30aztenghui                        newPath = new VFullPath((VFullPath) copyChild);
1236a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else if (copyChild instanceof VClipPath) {
1237a95c8abb366d9c39450513335f550b56da13b30aztenghui                        newPath = new VClipPath((VClipPath) copyChild);
1238a95c8abb366d9c39450513335f550b56da13b30aztenghui                    } else {
1239a95c8abb366d9c39450513335f550b56da13b30aztenghui                        throw new IllegalStateException("Unknown object in the tree!");
1240a95c8abb366d9c39450513335f550b56da13b30aztenghui                    }
12418d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(newPath);
12428d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (newPath.mPathName != null) {
12438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        targetsMap.put(newPath.mPathName, newPath);
12448d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
124555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                }
124655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
124755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
124855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
124955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup() {
125055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
125155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
1252a95c8abb366d9c39450513335f550b56da13b30aztenghui        public String getGroupName() {
1253a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mGroupName;
1254a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1255a95c8abb366d9c39450513335f550b56da13b30aztenghui
1256a95c8abb366d9c39450513335f550b56da13b30aztenghui        public Matrix getLocalMatrix() {
1257a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mLocalMatrix;
1258a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1259a95c8abb366d9c39450513335f550b56da13b30aztenghui
1260a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
1261a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(res, theme, attrs,
1262a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawableGroup);
1263a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1264a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1265a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1266a95c8abb366d9c39450513335f550b56da13b30aztenghui
1267a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1268a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1269a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1270a95c8abb366d9c39450513335f550b56da13b30aztenghui
1271a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Extract the theme attributes, if any.
1272a95c8abb366d9c39450513335f550b56da13b30aztenghui            mThemeAttrs = a.extractThemeAttrs();
1273a95c8abb366d9c39450513335f550b56da13b30aztenghui
1274a95c8abb366d9c39450513335f550b56da13b30aztenghui            mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
1275a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
1276a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
1277a95c8abb366d9c39450513335f550b56da13b30aztenghui            mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
1278a95c8abb366d9c39450513335f550b56da13b30aztenghui            mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
1279a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
1280a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
1281a95c8abb366d9c39450513335f550b56da13b30aztenghui
1282a95c8abb366d9c39450513335f550b56da13b30aztenghui            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
1283a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (groupName != null) {
1284a95c8abb366d9c39450513335f550b56da13b30aztenghui                mGroupName = groupName;
1285a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1286a95c8abb366d9c39450513335f550b56da13b30aztenghui
1287a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateLocalMatrix();
1288a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1289a95c8abb366d9c39450513335f550b56da13b30aztenghui
1290607bd848269fb802550e63aa61945790616f97a7Alan Viverette        public boolean canApplyTheme() {
1291607bd848269fb802550e63aa61945790616f97a7Alan Viverette            return mThemeAttrs != null;
1292607bd848269fb802550e63aa61945790616f97a7Alan Viverette        }
1293607bd848269fb802550e63aa61945790616f97a7Alan Viverette
1294a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1295a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mThemeAttrs == null) {
1296a95c8abb366d9c39450513335f550b56da13b30aztenghui                return;
1297a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1298a95c8abb366d9c39450513335f550b56da13b30aztenghui
1299607bd848269fb802550e63aa61945790616f97a7Alan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawableGroup);
1300a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1301a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1302a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1303a95c8abb366d9c39450513335f550b56da13b30aztenghui
1304a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateLocalMatrix() {
1305a95c8abb366d9c39450513335f550b56da13b30aztenghui            // The order we apply is the same as the
1306a95c8abb366d9c39450513335f550b56da13b30aztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
1307a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.reset();
1308a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
1309a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
1310a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
1311a95c8abb366d9c39450513335f550b56da13b30aztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
1312a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1313a95c8abb366d9c39450513335f550b56da13b30aztenghui
1314a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1315a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1316e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getRotation() {
1317e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mRotate;
1318e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1319e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1320a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1321e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setRotation(float rotation) {
1322e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (rotation != mRotate) {
1323e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mRotate = rotation;
1324e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1325e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1326e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1327e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1328a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1329e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotX() {
1330e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotX;
1331e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1333a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1334e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotX(float pivotX) {
1335e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotX != mPivotX) {
1336e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotX = pivotX;
1337e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1338e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1339e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1340e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1341a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1342e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotY() {
1343e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotY;
1344e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1345e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1346a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1347e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotY(float pivotY) {
1348e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotY != mPivotY) {
1349e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotY = pivotY;
1350e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1351e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1352e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1353e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1354a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1355e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleX() {
1356e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleX;
1357e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
13584d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1359a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1360e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleX(float scaleX) {
1361e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleX != mScaleX) {
1362e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleX = scaleX;
1363e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1364e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1365e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1366e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1367a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1368e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleY() {
1369e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleY;
1370e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1371e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1372a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1373e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleY(float scaleY) {
1374e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleY != mScaleY) {
1375e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleY = scaleY;
1376e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1377e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1378e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1379e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1380a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1381e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateX() {
1382e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateX;
1383e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1384e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1385a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1386e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateX(float translateX) {
1387e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateX != mTranslateX) {
1388e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateX = translateX;
1389e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1390e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1391e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1392e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1393a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1394e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateY() {
1395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateY;
1396e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1397e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1398a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1399e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateY(float translateY) {
1400e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateY != mTranslateY) {
1401e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateY = translateY;
1402e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
1403e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1404e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1405a95c8abb366d9c39450513335f550b56da13b30aztenghui    }
1406e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1407a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1408a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Common Path information for clip path and normal path.
1409a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
1410a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VPath {
1411a95c8abb366d9c39450513335f550b56da13b30aztenghui        protected PathParser.PathDataNode[] mNodes = null;
1412a95c8abb366d9c39450513335f550b56da13b30aztenghui        String mPathName;
1413a95c8abb366d9c39450513335f550b56da13b30aztenghui        int mChangingConfigurations;
1414a95c8abb366d9c39450513335f550b56da13b30aztenghui
1415a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VPath() {
1416a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Empty constructor.
14174d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
14184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1419a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VPath(VPath copy) {
1420a95c8abb366d9c39450513335f550b56da13b30aztenghui            mPathName = copy.mPathName;
1421a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations = copy.mChangingConfigurations;
1422a95c8abb366d9c39450513335f550b56da13b30aztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
14234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
14244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1425a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void toPath(Path path) {
1426a95c8abb366d9c39450513335f550b56da13b30aztenghui            path.reset();
1427a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mNodes != null) {
1428a95c8abb366d9c39450513335f550b56da13b30aztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
1429a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
14304d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
14314d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1432a95c8abb366d9c39450513335f550b56da13b30aztenghui        public String getPathName() {
1433a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mPathName;
14348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
14358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
1436a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean canApplyTheme() {
1437a95c8abb366d9c39450513335f550b56da13b30aztenghui            return false;
1438a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
143963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1440a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1441a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
144263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1443a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean isClipPath() {
1444a95c8abb366d9c39450513335f550b56da13b30aztenghui            return false;
1445a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
144663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1447a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1448a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1449a95c8abb366d9c39450513335f550b56da13b30aztenghui        public PathParser.PathDataNode[] getPathData() {
1450a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mNodes;
1451a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1452a95c8abb366d9c39450513335f550b56da13b30aztenghui
1453a95c8abb366d9c39450513335f550b56da13b30aztenghui        @SuppressWarnings("unused")
1454a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
1455a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
1456a95c8abb366d9c39450513335f550b56da13b30aztenghui                // This should not happen in the middle of animation.
1457a95c8abb366d9c39450513335f550b56da13b30aztenghui                mNodes = PathParser.deepCopyNodes(nodes);
1458a95c8abb366d9c39450513335f550b56da13b30aztenghui            } else {
1459a95c8abb366d9c39450513335f550b56da13b30aztenghui                PathParser.updateNodes(mNodes, nodes);
146063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            }
1461a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1462a95c8abb366d9c39450513335f550b56da13b30aztenghui    }
146363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1464a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1465a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Clip path, which only has name and pathData.
1466a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
14678490354dc651dd8f25036ef0dda7917fb33013edztenghui    private static class VClipPath extends VPath {
1468a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VClipPath() {
1469a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Empty constructor.
14708e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
14714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1472a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VClipPath(VClipPath copy) {
1473a95c8abb366d9c39450513335f550b56da13b30aztenghui            super(copy);
1474a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
14754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
1476a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
1477a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1478a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawableClipPath);
14798e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
148063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
148163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        }
148263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
1483a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1484a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1485a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1486a95c8abb366d9c39450513335f550b56da13b30aztenghui
14875004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name);
14885004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathName != null) {
14895004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mPathName = pathName;
14905004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
14915004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette
14925004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData);
14935004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathData != null) {
14945004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mNodes = PathParser.createNodesFromPathData(pathData);
14955004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
1496a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1497a95c8abb366d9c39450513335f550b56da13b30aztenghui
1498a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1499a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean isClipPath() {
1500a95c8abb366d9c39450513335f550b56da13b30aztenghui            return true;
15014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
1502abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1503abb7d134c02ac60091108c491dafb00877093170John Hoford
1504a95c8abb366d9c39450513335f550b56da13b30aztenghui    /**
1505a95c8abb366d9c39450513335f550b56da13b30aztenghui     * Normal path, which contains all the fill / paint information.
1506a95c8abb366d9c39450513335f550b56da13b30aztenghui     */
1507a95c8abb366d9c39450513335f550b56da13b30aztenghui    private static class VFullPath extends VPath {
150855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
150955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
15109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private int[] mThemeAttrs;
15119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1512a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui        int mStrokeColor = Color.TRANSPARENT;
1513abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeWidth = 0;
15142e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
1515a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui        int mFillColor = Color.TRANSPARENT;
15162e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        float mStrokeAlpha = 1.0f;
1517abb7d134c02ac60091108c491dafb00877093170John Hoford        int mFillRule;
15182e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        float mFillAlpha = 1.0f;
1519abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathStart = 0;
1520abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathEnd = 1;
1521abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathOffset = 0;
15229453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
15234b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
15244b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
1525abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeMiterlimit = 4;
15269453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1527a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VFullPath() {
15289453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            // Empty constructor.
15299453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
15309453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1531a95c8abb366d9c39450513335f550b56da13b30aztenghui        public VFullPath(VFullPath copy) {
1532a95c8abb366d9c39450513335f550b56da13b30aztenghui            super(copy);
153355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
153455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
153555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeColor = copy.mStrokeColor;
153655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeWidth = copy.mStrokeWidth;
15372e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = copy.mStrokeAlpha;
153855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillColor = copy.mFillColor;
153955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillRule = copy.mFillRule;
15402e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = copy.mFillAlpha;
154155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathStart = copy.mTrimPathStart;
154255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathEnd = copy.mTrimPathEnd;
154355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathOffset = copy.mTrimPathOffset;
154455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
154555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineCap = copy.mStrokeLineCap;
154655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
154755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
1548abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1549abb7d134c02ac60091108c491dafb00877093170John Hoford
15507f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
15517f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
15527f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_BUTT:
15537f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.BUTT;
15547f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_ROUND:
15557f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.ROUND;
15567f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_SQUARE:
15577f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.SQUARE;
15587f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
15597f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
15607f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
15617f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
15627f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
15637f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
15647f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
15657f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_MITER:
15667f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.MITER;
15677f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_ROUND:
15687f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.ROUND;
15697f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_BEVEL:
15707f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.BEVEL;
15717f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
15727f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
15737f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
15747f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
15757f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
1576a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1577a95c8abb366d9c39450513335f550b56da13b30aztenghui        public boolean canApplyTheme() {
1578a95c8abb366d9c39450513335f550b56da13b30aztenghui            return mThemeAttrs != null;
1579eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1580eb034fbca40006c55db143047eb628c4b657730aztenghui
1581a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
1582a95c8abb366d9c39450513335f550b56da13b30aztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1583a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath);
1584a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1585a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1586a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1587a95c8abb366d9c39450513335f550b56da13b30aztenghui
1588a95c8abb366d9c39450513335f550b56da13b30aztenghui        private void updateStateFromTypedArray(TypedArray a) {
1589a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Account for any configuration changes.
1590a95c8abb366d9c39450513335f550b56da13b30aztenghui            mChangingConfigurations |= a.getChangingConfigurations();
1591a95c8abb366d9c39450513335f550b56da13b30aztenghui
1592a95c8abb366d9c39450513335f550b56da13b30aztenghui            // Extract the theme attributes, if any.
1593a95c8abb366d9c39450513335f550b56da13b30aztenghui            mThemeAttrs = a.extractThemeAttrs();
1594a95c8abb366d9c39450513335f550b56da13b30aztenghui
15955004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathName = a.getString(R.styleable.VectorDrawablePath_name);
15965004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathName != null) {
15975004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mPathName = pathName;
15985004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
15995004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette
16005004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData);
16015004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            if (pathData != null) {
16025004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette                mNodes = PathParser.createNodesFromPathData(pathData);
16035004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette            }
1604a95c8abb366d9c39450513335f550b56da13b30aztenghui
1605a95c8abb366d9c39450513335f550b56da13b30aztenghui            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor,
1606a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mFillColor);
16072e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha,
16082e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui                    mFillAlpha);
1609a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeLineCap = getStrokeLineCap(a.getInt(
1610a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
1611a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
1612a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
1613a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeMiterlimit = a.getFloat(
1614a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
1615a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor,
1616a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mStrokeColor);
16172e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha,
16182e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui                    mStrokeAlpha);
1619a95c8abb366d9c39450513335f550b56da13b30aztenghui            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth,
1620a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mStrokeWidth);
1621a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd,
1622a95c8abb366d9c39450513335f550b56da13b30aztenghui                    mTrimPathEnd);
1623a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathOffset = a.getFloat(
1624a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
1625a95c8abb366d9c39450513335f550b56da13b30aztenghui            mTrimPathStart = a.getFloat(
1626a95c8abb366d9c39450513335f550b56da13b30aztenghui                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
1627a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1628a95c8abb366d9c39450513335f550b56da13b30aztenghui
1629a95c8abb366d9c39450513335f550b56da13b30aztenghui        @Override
1630a95c8abb366d9c39450513335f550b56da13b30aztenghui        public void applyTheme(Theme t) {
1631a95c8abb366d9c39450513335f550b56da13b30aztenghui            if (mThemeAttrs == null) {
1632a95c8abb366d9c39450513335f550b56da13b30aztenghui                return;
1633a95c8abb366d9c39450513335f550b56da13b30aztenghui            }
1634a95c8abb366d9c39450513335f550b56da13b30aztenghui
1635607bd848269fb802550e63aa61945790616f97a7Alan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
1636a95c8abb366d9c39450513335f550b56da13b30aztenghui            updateStateFromTypedArray(a);
1637a95c8abb366d9c39450513335f550b56da13b30aztenghui            a.recycle();
1638a95c8abb366d9c39450513335f550b56da13b30aztenghui        }
1639a95c8abb366d9c39450513335f550b56da13b30aztenghui
1640a95c8abb366d9c39450513335f550b56da13b30aztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
1641eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1642dbcccffc3760f702887faa95b2748125bac88a89ztenghui        int getStrokeColor() {
1643e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeColor;
1644e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1645e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1646eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1647dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setStrokeColor(int strokeColor) {
1648e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeColor = strokeColor;
1649e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1650e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1651eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1652e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeWidth() {
1653e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeWidth;
1654e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1655e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1656eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1657e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeWidth(float strokeWidth) {
1658e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeWidth = strokeWidth;
1659e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1660e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1661eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1662dbcccffc3760f702887faa95b2748125bac88a89ztenghui        float getStrokeAlpha() {
16632e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            return mStrokeAlpha;
16642e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
16652e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
16662e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1667dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setStrokeAlpha(float strokeAlpha) {
16682e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mStrokeAlpha = strokeAlpha;
16692e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
16702e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
16712e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1672dbcccffc3760f702887faa95b2748125bac88a89ztenghui        int getFillColor() {
1673e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillColor;
1674e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1675e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1676eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1677dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setFillColor(int fillColor) {
1678e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillColor = fillColor;
1679e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1680e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1681eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1682dbcccffc3760f702887faa95b2748125bac88a89ztenghui        float getFillAlpha() {
16832e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            return mFillAlpha;
16842e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
16852e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
16862e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1687dbcccffc3760f702887faa95b2748125bac88a89ztenghui        void setFillAlpha(float fillAlpha) {
16882e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui            mFillAlpha = fillAlpha;
16892e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        }
16902e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui
16912e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui        @SuppressWarnings("unused")
1692e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathStart() {
1693e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathStart;
1694e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1695e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1696eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1697e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathStart(float trimPathStart) {
1698e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathStart = trimPathStart;
1699e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1700e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1701eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1702e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathEnd() {
1703e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathEnd;
1704e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1705e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1706eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1707e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathEnd(float trimPathEnd) {
1708e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathEnd = trimPathEnd;
1709e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1710e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1711eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1712e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathOffset() {
1713e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathOffset;
1714e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1715e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1716eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1717e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathOffset(float trimPathOffset) {
1718e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathOffset = trimPathOffset;
1719e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1720abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1721abb7d134c02ac60091108c491dafb00877093170John Hoford}
1722