VectorDrawableCompat.java revision 791d564c66cf6bfc38413a35bf767b41cf019887
14fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/*
24fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Copyright (C) 2015 The Android Open Source Project
34fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
44fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
54fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * in compliance with the License. You may obtain a copy of the License at
64fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
74fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * http://www.apache.org/licenses/LICENSE-2.0
84fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
94fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Unless required by applicable law or agreed to in writing, software distributed under the License
104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * or implied. See the License for the specific language governing permissions and limitations under
124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * the License.
134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuipackage android.support.graphics.drawable;
164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1767b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport static android.support.annotation.RestrictTo.Scope.GROUP_ID;
18e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.annotation.TargetApi;
204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.ColorStateList;
214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources;
224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources.Theme;
234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.TypedArray;
244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Bitmap;
254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Canvas;
264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Color;
274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.ColorFilter;
284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Matrix;
294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Paint;
304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Path;
314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PathMeasure;
324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PixelFormat;
334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff;
344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff.Mode;
354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuffColorFilter;
364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Rect;
374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.drawable.Drawable;
389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.graphics.drawable.VectorDrawable;
399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.os.Build;
40968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhuimport android.support.annotation.DrawableRes;
414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.NonNull;
424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.Nullable;
4367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.annotation.RestrictTo;
4467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.content.res.ResourcesCompat;
4567b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.graphics.drawable.DrawableCompat;
464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.v4.util.ArrayMap;
474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.AttributeSet;
480327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhuimport android.util.LayoutDirection;
494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Log;
504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Xml;
514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5267b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport org.xmlpull.v1.XmlPullParser;
5367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport org.xmlpull.v1.XmlPullParserException;
5467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu
554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.io.IOException;
564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.ArrayList;
574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.Stack;
584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/**
60c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
61ab9d2bf6fe28ff4a95985526daa128239c03d821Teng-Hui Zhu * For older API version, this class lets you create a drawable based on an XML vector graphic.
6295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
637c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API.
647c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * In order to refer to VectorDrawableCompat inside a XML file,  you can use app:srcCompat attribute
657c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * in AppCompat library's ImageButton or ImageView.
6695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
6795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <strong>Note:</strong> To optimize for the re-drawing performance, one bitmap cache is created
6895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * for each VectorDrawableCompat. Therefore, referring to the same VectorDrawableCompat means
6995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * sharing the same bitmap cache. If these references don't agree upon on the same size, the bitmap
7095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * will be recreated and redrawn every time size is changed. In other words, if a VectorDrawable is
7195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * used for different sizes, it is more efficient to create multiple VectorDrawables, one for each
7295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * size.
7395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * VectorDrawableCompat can be defined in an XML file with the <code>&lt;vector></code> element.
7595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The VectorDrawableCompat has the following elements:
7795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;vector></code></dt>
7995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define a vector drawable
8195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
8395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of this vector drawable.</dd>
8495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:width</code></dt>
8595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic width of the drawable.
8695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
8795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:height</code></dt>
8895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic height the drawable.
8995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
9095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportWidth</code></dt>
9195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the width of the viewport space. Viewport is basically
9295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportHeight</code></dt>
9495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the height of the viewport space. Viewport is basically
9595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tint</code></dt>
9795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
9895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tintMode</code></dt>
99791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd>
10095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:autoMirrored</code></dt>
10195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
102791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * RTL (right-to-left). Default is false.</dd>
10395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:alpha</code></dt>
104791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of this drawable. Default is 1.</dd>
10595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
10695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
10795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
10895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
10995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;group></code></dt>
11095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines a group of paths or subgroups, plus transformation information.
11195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The transformations are defined in the same coordinates as the viewport.
11295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * And the transformations are applied in the order of scale, rotate then translate.
11395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
11495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
11595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the group.</dd>
11695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:rotation</code></dt>
117791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The degrees of rotation of the group. Default is 0.</dd>
11895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotX</code></dt>
11995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The X coordinate of the pivot for the scale and rotation of the group.
120791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotY</code></dt>
12295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
123791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleX</code></dt>
125791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the X Coordinate. Default is 1.</dd>
12695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleY</code></dt>
127791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the Y coordinate. Default is 1.</dd>
12895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateX</code></dt>
12995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the X coordinate.
130791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateY</code></dt>
13295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the Y coordinate.
133791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
13595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
13695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
13795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
13895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;path></code></dt>
13995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines paths to be drawn.
14095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
14195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
14295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the path.</dd>
14395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
14495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path data using exactly same format as "d" attribute
14595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data. This is defined in the viewport space.</dd>
14695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillColor</code></dt>
14795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to fill the path.
14895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
14995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path fill is drawn if this property is not specified.</dd>
15095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeColor</code></dt>
15195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to draw the path outline.
15295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
15395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path outline is drawn if this property is not specified.</dd>
15495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeWidth</code></dt>
155791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The width a path stroke. Default is 0.</dd>
15695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeAlpha</code></dt>
157791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of a path stroke. Default is 1.</dd>
15895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillAlpha</code></dt>
159791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity to fill the path with. Default is 1.</dd>
16095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathStart</code></dt>
161791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd>
16295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathEnd</code></dt>
163791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd>
16495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathOffset</code></dt>
16595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Shift trim region (allows showed region to include the start and end), in the range
166791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * from 0 to 1. Default is 0.</dd>
16795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineCap</code></dt>
168791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd>
16995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineJoin</code></dt>
170791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
17195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeMiterLimit</code></dt>
172791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
17395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
17495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
17595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
17695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
17795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;clip-path></code></dt>
17895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path to be the current clip. Note that the clip path only apply to
17995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the current group and its children.
18095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
18195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
18295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the clip path.</dd>
18395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
18495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines clip path using the same format as "d" attribute
18595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data.</dd>
18695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
18795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
188791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <p/>
189791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * Note that theme attributes in XML file are supported through
190791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <code>{@link #inflate(Resources, XmlPullParser, AttributeSet, Theme)}</code>.
1914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
19295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu
1939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu@TargetApi(Build.VERSION_CODES.LOLLIPOP)
194968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhupublic class VectorDrawableCompat extends VectorDrawableCommon {
1954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final String LOGTAG = "VectorDrawableCompat";
1964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
1984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_CLIP_PATH = "clip-path";
2004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_GROUP = "group";
2014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_PATH = "path";
2024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_VECTOR = "vector";
2034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_BUTT = 0;
2054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_ROUND = 1;
2064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_SQUARE = 2;
2074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_MITER = 0;
2094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_ROUND = 1;
2104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_BEVEL = 2;
2114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Cap the bitmap size, such that it won't hurt the performance too much
2131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // and it won't crash due to a very large scale.
2141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // The drawable will look blurry above this size.
2151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private static final int MAX_CACHED_BITMAP_SIZE = 2048;
2161f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
217d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    private static final boolean DBG_VECTOR_DRAWABLE = false;
2184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private VectorDrawableCompatState mVectorState;
2204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private PorterDuffColorFilter mTintFilter;
2224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private ColorFilter mColorFilter;
2234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mMutated;
2254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
2274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // caching the bitmap by default is allowed.
2284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mAllowCaching = true;
2294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // The Constant state associated with the <code>mDelegateDrawable</code>.
2319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private ConstantState mCachedConstantStateDelegate;
2329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2331f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Temp variable, only for saving "new" operation at the draw() time.
2341f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final float[] mTmpFloats = new float[9];
2351f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Matrix mTmpMatrix = new Matrix();
2361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Rect mTmpBounds = new Rect();
2371f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
2388fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat() {
2399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        mVectorState = new VectorDrawableCompatState();
2404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2428fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat(@NonNull VectorDrawableCompatState state) {
2434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState = state;
2444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
2454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public Drawable mutate() {
2499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.mutate();
2519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return this;
2529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mMutated && super.mutate() == this) {
2559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mVectorState = new VectorDrawableCompatState(mVectorState);
2564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mMutated = true;
2574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return this;
2594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    Object getTargetByName(String name) {
2624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
2634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public ConstantState getConstantState() {
2679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Such that the configuration can be refreshed.
2692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return new VectorDrawableDelegateState(mDelegateDrawable.getConstantState());
2709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
2724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState;
2734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void draw(Canvas canvas) {
2779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.draw(canvas);
2799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2811f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // We will offset the bounds for drawBitmap, so copyBounds() here instead
2821f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // of getBounds().
2831f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        copyBounds(mTmpBounds);
2841f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
2851f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            // Nothing to draw
2861f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            return;
2871f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
2889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Color filters always override tint filters.
2901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
2911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
2921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // The imageView can scale the canvas in different ways, in order to
2931f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
2941f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // size first. This bitmap size is determined by the bounds and the
2951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // canvas scale.
2961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.getMatrix(mTmpMatrix);
2971f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpMatrix.getValues(mTmpFloats);
2981f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
2991f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
3001f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3011f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewX = Math.abs(mTmpFloats[Matrix.MSKEW_X]);
3021f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewY = Math.abs(mTmpFloats[Matrix.MSKEW_Y]);
3031f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3041f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // When there is any rotation / skew, then the scale value is not valid.
3051f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (canvasSkewX != 0 || canvasSkewY != 0) {
3061f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleX = 1.0f;
3071f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleY = 1.0f;
3081f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
3091f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3101f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
3111f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
3121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
3131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
3141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (scaledWidth <= 0 || scaledHeight <= 0) {
3164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return;
3174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int saveCount = canvas.save();
3201f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.translate(mTmpBounds.left, mTmpBounds.top);
3214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3221f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Handle RTL mirroring.
3231f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final boolean needMirroring = needMirroring();
3244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (needMirroring) {
3251f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.translate(mTmpBounds.width(), 0);
3264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            canvas.scale(-1.0f, 1.0f);
3274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3291f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // At this point, canvas has been translated to the right position.
3301f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // And we use this bound for the destination rect for the drawBitmap, so
3311f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // we offset to (0, 0);
3321f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpBounds.offsetTo(0, 0);
3334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3341f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
3354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mAllowCaching) {
3361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
3374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else {
3384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mVectorState.canReuseCache()) {
3391f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
3404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.updateCacheStates();
3414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
3424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3431f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
3444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        canvas.restoreToCount(saveCount);
3454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
34715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
3484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getAlpha() {
3499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
350ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompat.getAlpha(mDelegateDrawable);
3519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
3544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setAlpha(int alpha) {
3589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setAlpha(alpha);
3609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
3619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
3644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
3654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
3664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setColorFilter(ColorFilter colorFilter) {
3719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setColorFilter(colorFilter);
3739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
3749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mColorFilter = colorFilter;
3774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        invalidateSelf();
3784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
3814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Ensures the tint filter is consistent with the current tint color and
3824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * mode.
3834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
3844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
3852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                           PorterDuff.Mode tintMode) {
3864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint == null || tintMode == null) {
3874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return null;
3884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7.
3904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Therefore we create a new one all the time here. Don't expect this is called often.
3914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
3924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return new PorterDuffColorFilter(color, tintMode);
3934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
39515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
3964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTint(int tint) {
3979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
398ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTint(mDelegateDrawable, tint);
3999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        setTintList(ColorStateList.valueOf(tint));
4034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
40515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintList(ColorStateList tint) {
4079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
408ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintList(mDelegateDrawable, tint);
4099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != tint) {
4144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
4154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
4164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
42015375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintMode(Mode tintMode) {
4229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
423ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintMode(mDelegateDrawable, tintMode);
4249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTintMode != tintMode) {
4294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTintMode = tintMode;
4304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
4314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean isStateful() {
4379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.isStateful();
4399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
4424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                && mVectorState.mTint.isStateful());
4434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    protected boolean onStateChange(int[] stateSet) {
4479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setState(stateSet);
4499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != null && state.mTintMode != null) {
4539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
4544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
4564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
4584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getOpacity() {
4629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getOpacity();
4649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return PixelFormat.TRANSLUCENT;
4674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicWidth() {
4719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicWidth();
4739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
4764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicHeight() {
4809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicHeight();
4829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
4854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // Don't support re-applying themes. The initial theme loading is working.
48815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean canApplyTheme() {
4909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
491ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.canApplyTheme(mDelegateDrawable);
4929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
4954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4970327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    @Override
4980327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    public boolean isAutoMirrored() {
4990327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (mDelegateDrawable != null) {
5000327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return DrawableCompat.isAutoMirrored(mDelegateDrawable);
5010327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
5020327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        return mVectorState.mAutoMirrored;
5030327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    }
5040327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu
5050327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    @Override
5060327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    public void setAutoMirrored(boolean mirrored) {
5070327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (mDelegateDrawable != null) {
5080327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            DrawableCompat.setAutoMirrored(mDelegateDrawable, mirrored);
5090327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return;
5100327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
5110327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        mVectorState.mAutoMirrored = mirrored;
5120327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    }
5134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
5144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This
5154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * is used to calculate the path animation accuracy.
5164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
5174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @hide
5184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
519c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette    @RestrictTo(GROUP_ID)
5204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public float getPixelSize() {
5214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (mVectorState == null && mVectorState.mVPathRenderer == null ||
5224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
5234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
5244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
5254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mViewportWidth == 0) {
5264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return 1; // fall back to 1:1 pixel mapping.
5274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
5294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
5304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
5314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
5324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleX = viewportWidth / intrinsicWidth;
5334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleY = viewportHeight / intrinsicHeight;
5344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return Math.min(scaleX, scaleY);
5354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
5384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Create a VectorDrawableCompat object.
5394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
5402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu     * @param res   the resources.
5414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param resId the resource ID for VectorDrawableCompat object.
5424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param theme the theme of this vector drawable, it can be null.
5434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @return a new VectorDrawableCompat or null if parsing error is found.
5444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
5454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Nullable
5464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId,
5472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                              @Nullable Theme theme) {
548c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu        if (Build.VERSION.SDK_INT >= 24) {
5499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final VectorDrawableCompat drawable = new VectorDrawableCompat();
550ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            drawable.mDelegateDrawable = ResourcesCompat.getDrawable(res, resId, theme);
5512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            drawable.mCachedConstantStateDelegate = new VectorDrawableDelegateState(
5522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    drawable.mDelegateDrawable.getConstantState());
5539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawable;
5549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
5559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
5564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        try {
5574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final XmlPullParser parser = res.getXml(resId);
5584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final AttributeSet attrs = Xml.asAttributeSet(parser);
5594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            int type;
5604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            while ((type = parser.next()) != XmlPullParser.START_TAG &&
5614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    type != XmlPullParser.END_DOCUMENT) {
5624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // Empty loop
5634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
5644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (type != XmlPullParser.START_TAG) {
5654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                throw new XmlPullParserException("No start tag found");
5664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
567e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            return createFromXmlInner(res, parser, attrs, theme);
5684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (XmlPullParserException e) {
5694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
5704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (IOException e) {
5714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
5724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return null;
5744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
576e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    /**
577e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * Create a VectorDrawableCompat from inside an XML document using an optional
578e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * {@link Theme}. Called on a parser positioned at a tag in an XML
579e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * document, tries to create a Drawable from that tag. Returns {@code null}
580e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * if the tag is not a valid drawable.
581e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     */
582e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    public static VectorDrawableCompat createFromXmlInner(Resources r, XmlPullParser parser,
583e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
584e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        final VectorDrawableCompat drawable = new VectorDrawableCompat();
585e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        drawable.inflate(r, parser, attrs, theme);
586e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        return drawable;
587e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    }
588e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
5898fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    static int applyAlpha(int color, float alpha) {
5904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int alphaBytes = Color.alpha(color);
5914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color &= 0x00FFFFFF;
5924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
5934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return color;
5944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
5974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
5984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
5999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
6009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.inflate(res, parser, attrs);
6019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
6029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflate(res, parser, attrs, null);
6054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
60715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
6084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
6094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
6109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
611ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.inflate(mDelegateDrawable, res, parser, attrs, theme);
6129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
6139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
6164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
6174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mVPathRenderer = pathRenderer;
6184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final TypedArray a = obtainAttributes(res, theme, attrs,
6209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawableTypeArray);
621d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
622d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        updateStateFromTypedArray(a, parser);
6234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        a.recycle();
6244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mChangingConfigurations = getChangingConfigurations();
6254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mCacheDirty = true;
6264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflateInternal(res, parser, attrs, theme);
6274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
6294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
631d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
632d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    /**
633d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
634d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * attribute's enum value.
635d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     */
6366705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu    private static PorterDuff.Mode parseTintModeCompat(int value, Mode defaultMode) {
637d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        switch (value) {
6382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 3:
6392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_OVER;
6402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 5:
6412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_IN;
6422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 9:
6432c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_ATOP;
6442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 14:
6452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.MULTIPLY;
6462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 15:
6472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SCREEN;
6482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 16:
6492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.ADD;
6502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            default:
6512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return defaultMode;
652d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
653d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    }
654d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
6559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser)
6569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            throws XmlPullParserException {
6579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
6584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
6594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Account for any configuration changes.
6614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
6624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
663d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode",
664d014251a4529b0eae3c313b7ede2b9d18421de44Chris Banes                AndroidResources.styleable_VectorDrawable_tintMode, -1);
6656705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu        state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN);
6664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final ColorStateList tint =
6689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                a.getColorStateList(AndroidResources.styleable_VectorDrawable_tint);
6694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint != null) {
6704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
6714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
673d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored",
6742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_autoMirrored, state.mAutoMirrored);
675d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
676d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth",
6779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_viewportWidth,
6789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportWidth);
6794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
680d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight",
6819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_viewportHeight,
6829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportHeight);
6834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mViewportWidth <= 0) {
6854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportWidth > 0");
6874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
6884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportHeight > 0");
6904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseWidth = a.getDimension(
693d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_width, pathRenderer.mBaseWidth);
6944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseHeight = a.getDimension(
695d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_height, pathRenderer.mBaseHeight);
6964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mBaseWidth <= 0) {
6974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires width > 0");
6994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
7004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
7014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires height > 0");
7024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
704d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        // shown up from API 11.
705d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
706968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhu                AndroidResources.styleable_VectorDrawable_alpha, pathRenderer.getAlpha());
7074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.setAlpha(alphaInFloat);
7084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
709d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final String name = a.getString(AndroidResources.styleable_VectorDrawable_name);
7104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (name != null) {
7114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mRootName = name;
7124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
7134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
7172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                 Theme theme) throws XmlPullParserException, IOException {
7189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
7194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
7204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean noPathTag = true;
7214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Use a stack to help to build the group tree.
7234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // The top of the stack is always the current group.
7244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
7254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        groupStack.push(pathRenderer.mRootGroup);
7264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int eventType = parser.getEventType();
72867b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        final int innerDepth = parser.getDepth() + 1;
72967b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu
73067b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        // Parse everything until the end of the vector element.
73167b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        while (eventType != XmlPullParser.END_DOCUMENT
73267b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
7334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (eventType == XmlPullParser.START_TAG) {
7344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final VGroup currentGroup = groupStack.peek();
7364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_PATH.equals(tagName)) {
7374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VFullPath path = new VFullPath();
738d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    noPathTag = false;
7444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
7464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VClipPath path = new VClipPath();
747d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
7544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup newChildGroup = new VGroup();
755d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    newChildGroup.inflate(res, attrs, theme, parser);
7564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(newChildGroup);
7574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.push(newChildGroup);
7584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newChildGroup.getGroupName() != null) {
7594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
7604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                                newChildGroup);
7614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
7634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
7654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_GROUP.equals(tagName)) {
7674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.pop();
7684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            eventType = parser.next();
7714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the tree out for debug.
7744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (DBG_VECTOR_DRAWABLE) {
7754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
7764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (noPathTag) {
7794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final StringBuffer tag = new StringBuffer();
7804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (tag.length() > 0) {
7824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                tag.append(" or ");
7834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            tag.append(SHAPE_PATH);
7854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException("no " + tag + " defined");
7874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
7914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String indent = "";
7924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < level; i++) {
7934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            indent += "    ";
7944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the current node
7964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
7974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                + " rotation is " + currentGroup.mRotate);
7984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
7994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Then print all the children groups
8004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
8014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Object child = currentGroup.mChildren.get(i);
8024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (child instanceof VGroup) {
8034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                printGroupTree((VGroup) child, level + 1);
804d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            } else {
805d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                ((VPath) child).printVPath(level + 1);
8064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    void setAllowCaching(boolean allowCaching) {
8114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mAllowCaching = allowCaching;
8124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
8154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean needMirroring() {
8160327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (Build.VERSION.SDK_INT < 17) {
8170327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return false;
8180327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        } else {
8190327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
8200327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
8214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // Extra override functions for delegation for SDK >= 7.
8249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8255f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu    protected void onBoundsChange(Rect bounds) {
8269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8275f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu            mDelegateDrawable.setBounds(bounds);
8289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public int getChangingConfigurations() {
8339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getChangingConfigurations();
8359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8362c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
8379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void invalidateSelf() {
8419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.invalidateSelf();
8439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.invalidateSelf();
8469f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void scheduleSelf(Runnable what, long when) {
8509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.scheduleSelf(what, when);
8529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.scheduleSelf(what, when);
8559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public boolean setVisible(boolean visible, boolean restart) {
8599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setVisible(visible, restart);
8619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        return super.setVisible(visible, restart);
8639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void unscheduleSelf(Runnable what) {
8679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.unscheduleSelf(what);
8699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.unscheduleSelf(what);
8729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    /**
875c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu     * Constant state for delegating the creating drawable job for SDK >= 24.
8769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains
8779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * a delegated VectorDrawable instance.
8789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     */
8799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableDelegateState extends ConstantState {
8809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        private final ConstantState mDelegateState;
8812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
8829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableDelegateState(ConstantState state) {
8839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateState = state;
8849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
8879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable() {
8889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
8899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable();
8909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
8919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
8949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res) {
8959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
8969f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(res);
8979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
8989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res, Theme theme) {
9029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable =
9049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    (VectorDrawable) mDelegateState.newDrawable(res, theme);
9059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public boolean canApplyTheme() {
9109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.canApplyTheme();
9119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public int getChangingConfigurations() {
9159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.getChangingConfigurations();
9169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
9189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableCompatState extends ConstantState {
9204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
9214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        VPathRenderer mVPathRenderer;
9224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mTint = null;
9234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mTintMode = DEFAULT_TINT_MODE;
9244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mAutoMirrored;
9254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Bitmap mCachedBitmap;
9274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int[] mCachedThemeAttrs;
9284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mCachedTint;
9294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mCachedTintMode;
9304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mCachedRootAlpha;
9314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCachedAutoMirrored;
9324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCacheDirty;
9334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9342c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        /**
9352c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         * Temporary paint object used to draw cached bitmaps.
9362c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         */
9374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint mTempPaint;
9384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Deep copy for mutate() or implicitly mutate.
9409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState(VectorDrawableCompatState copy) {
9414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy != null) {
9424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mChangingConfigurations = copy.mChangingConfigurations;
9434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
9444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mFillPaint != null) {
9454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
9464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mStrokePaint != null) {
9484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
9494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTint = copy.mTint;
9514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTintMode = copy.mTintMode;
9524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mAutoMirrored = copy.mAutoMirrored;
9534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9561f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
9571f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                                                  Rect originalBounds) {
9584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The bitmap's size is the same as the bounds.
9594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Paint p = getPaint(filter);
9601f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
9614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean hasTranslucentRoot() {
9644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mVPathRenderer.getRootAlpha() < 255;
9654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /**
9684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * @return null when there is no need for alpha paint.
9694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
9704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Paint getPaint(ColorFilter filter) {
9714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!hasTranslucentRoot() && filter == null) {
9724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return null;
9734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mTempPaint == null) {
9764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint = new Paint();
9774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint.setFilterBitmap(true);
9784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
9804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setColorFilter(filter);
9814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTempPaint;
9824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9841f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void updateCachedBitmap(int width, int height) {
9854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
9864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
9871f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVPathRenderer.draw(tmpCanvas, width, height, null);
9884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void createCachedBitmapIfNeeded(int width, int height) {
9911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
9921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mCachedBitmap = Bitmap.createBitmap(width, height,
9934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        Bitmap.Config.ARGB_8888);
9944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mCacheDirty = true;
9954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseBitmap(int width, int height) {
10004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (width == mCachedBitmap.getWidth()
10014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && height == mCachedBitmap.getHeight()) {
10024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseCache() {
10084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mCacheDirty
10094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTint == mTint
10104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTintMode == mTintMode
10114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedAutoMirrored == mAutoMirrored
10124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
10134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void updateCacheStates() {
10194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
10204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // likely hit cache miss more, but practically not much difference.
10214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTint = mTint;
10224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTintMode = mTintMode;
10234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
10244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedAutoMirrored = mAutoMirrored;
10254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCacheDirty = false;
10264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState() {
10294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVPathRenderer = new VPathRenderer();
10304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable() {
10344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable(Resources res) {
10394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getChangingConfigurations() {
10444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mChangingConfigurations;
10454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
10474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPathRenderer {
10494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Right now the internal data structure is organized as a tree.
10504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * Each node can be a group node, or a path.
10514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * A group node can have groups or paths as children, but a path node has
10524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * no children.
10534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * One example can be:
10544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                 Root Group
10554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                /    |     \
10564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *           Group    Path    Group
10574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *          /     \             |
10584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *         Path   Path         Path
10594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *
10604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
10614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables that only used temporarily inside the draw() call, so there
10624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // is no need for deep copying.
10634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mPath;
10644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mRenderPath;
10654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
10664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mFinalPathMatrix = new Matrix();
10674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mStrokePaint;
10694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mFillPaint;
10704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private PathMeasure mPathMeasure;
10714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
10734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
10744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int mChangingConfigurations;
10758fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        final VGroup mRootGroup;
10764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseWidth = 0;
10774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseHeight = 0;
10784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportWidth = 0;
10794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportHeight = 0;
10804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mRootAlpha = 0xFF;
10814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mRootName = null;
10824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
10844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer() {
10864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup();
10874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path();
10884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path();
10894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRootAlpha(int alpha) {
10924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = alpha;
10934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getRootAlpha() {
10964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRootAlpha;
10974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
11004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Animator like to use alpha from 0 to 1.
11014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setAlpha(float alpha) {
11024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            setRootAlpha((int) (alpha * 255));
11034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
11064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getAlpha() {
11074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return getRootAlpha() / 255.0f;
11084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer(VPathRenderer copy) {
11114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
11124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path(copy.mPath);
11134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path(copy.mRenderPath);
11144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseWidth = copy.mBaseWidth;
11154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseHeight = copy.mBaseHeight;
11164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportWidth = copy.mViewportWidth;
11174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportHeight = copy.mViewportHeight;
11184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
11194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = copy.mRootAlpha;
11204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootName = copy.mRootName;
11214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy.mRootName != null) {
11224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVGTargetsMap.put(copy.mRootName, this);
11234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
11244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
11272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                   Canvas canvas, int w, int h, ColorFilter filter) {
11284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Calculate current group's matrix by preConcat the parent's and
11294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // and the current one on the top of the stack.
11304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
11314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Mi the local matrix at level i of the group tree.
11324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
11334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
11354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
113604027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            // Save the current clip information, which is local to this group.
113704027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.save();
113804027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
11394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Draw the group tree in the same order as the XML file.
11404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
11414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object child = currentGroup.mChildren.get(i);
11424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (child instanceof VGroup) {
11434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup childGroup = (VGroup) child;
11444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
11454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                            canvas, w, h, filter);
11464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (child instanceof VPath) {
11474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath childPath = (VPath) child;
11484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawPath(currentGroup, childPath, canvas, w, h, filter);
11494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
11504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
115104027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
115204027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.restore();
11534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
1156c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas            // Traverse the tree in pre-order to draw.
11574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
11584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
11612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                              ColorFilter filter) {
11624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleX = w / mViewportWidth;
11634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleY = h / mViewportHeight;
11644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float minScale = Math.min(scaleX, scaleY);
11652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
11664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFinalPathMatrix.set(groupStackedMatrix);
11684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
11694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final float matrixScale = getMatrixScale(groupStackedMatrix);
11722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (matrixScale == 0) {
11732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                // When either x or y is scaled to 0, we don't need to draw anything.
11742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return;
11752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
11764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            vPath.toPath(mPath);
11774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Path path = mPath;
11784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath.reset();
11804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (vPath.isClipPath()) {
11824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
118304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu                canvas.clipPath(mRenderPath);
11844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
11854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                VFullPath fullPath = (VFullPath) vPath;
11864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
11874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
11884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
11894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mPathMeasure == null) {
11914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure = new PathMeasure();
11924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
11934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mPathMeasure.setPath(mPath, false);
11944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float len = mPathMeasure.getLength();
11964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    start = start * len;
11974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    end = end * len;
11984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.reset();
11994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (start > end) {
12004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, len, path, true);
12014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(0f, end, path, true);
12024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
12034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, end, path, true);
12044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.rLineTo(0, 0); // fix bug in measure
12064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
12084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
12104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mFillPaint == null) {
12114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint = new Paint();
12124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
12134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setAntiAlias(true);
12144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint fillPaint = mFillPaint;
12174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
12184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColorFilter(filter);
12194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, fillPaint);
12204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
12234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mStrokePaint == null) {
12244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint = new Paint();
12254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
12264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setAntiAlias(true);
12274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint strokePaint = mStrokePaint;
12304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineJoin != null) {
12314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
12324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineCap != null) {
12354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
12364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
12394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
12404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColorFilter(filter);
12412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    final float finalStrokeScale = minScale * matrixScale;
12422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
12434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
12444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private static float cross(float v1x, float v1y, float v2x, float v2y) {
12492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return v1x * v2y - v1y * v2x;
12502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private float getMatrixScale(Matrix groupStackedMatrix) {
12532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Given unit vectors A = (0, 1) and B = (1, 0).
12542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
12552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
12562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
12572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
12582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            //
12592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
12602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // scale on x and y axis, and take the minimal of these two.
12612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For skew case, an unit square will mapped to a parallelogram. And this function will
12622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // return the minimal height of the 2 bases.
12632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float[] unitVectors = new float[]{0, 1, 1, 0};
12642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            groupStackedMatrix.mapVectors(unitVectors);
12652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]);
12662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]);
12672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2],
12682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    unitVectors[3]);
12692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float maxScale = Math.max(scaleX, scaleY);
12702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float matrixScale = 0;
12722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (maxScale > 0) {
12732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                matrixScale = Math.abs(crossProduct) / maxScale;
12742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (DBG_VECTOR_DRAWABLE) {
12762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
12772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return matrixScale;
12792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
12814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VGroup {
12834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
12844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // the parents' local matrices with the current one.
12854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mStackedMatrix = new Matrix();
12864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
12884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
12894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
12904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12918fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        float mRotate = 0;
12924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotX = 0;
12934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotY = 0;
12944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleX = 1;
12954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleY = 1;
12964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateX = 0;
12974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateY = 0;
12984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mLocalMatrix is updated based on the update of transformation information,
13004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // either parsed from the XML or by animation.
13014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mLocalMatrix = new Matrix();
13028fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        int mChangingConfigurations;
13034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
13044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private String mGroupName = null;
13054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
13074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRotate = copy.mRotate;
13084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotX = copy.mPivotX;
13094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotY = copy.mPivotY;
13104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleX = copy.mScaleX;
13114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleY = copy.mScaleY;
13124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateX = copy.mTranslateX;
13134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateY = copy.mTranslateY;
13144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
13154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mGroupName = copy.mGroupName;
13164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
13174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mGroupName != null) {
13184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                targetsMap.put(mGroupName, this);
13194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.set(copy.mLocalMatrix);
13224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final ArrayList<Object> children = copy.mChildren;
13244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < children.size(); i++) {
13254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object copyChild = children.get(i);
13264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copyChild instanceof VGroup) {
13274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup copyGroup = (VGroup) copyChild;
13284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
13294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else {
13304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath newPath = null;
13314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (copyChild instanceof VFullPath) {
13324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VFullPath((VFullPath) copyChild);
13334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else if (copyChild instanceof VClipPath) {
13344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VClipPath((VClipPath) copyChild);
13354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
13364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        throw new IllegalStateException("Unknown object in the tree!");
13374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(newPath);
13394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newPath.mPathName != null) {
13404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        targetsMap.put(newPath.mPathName, newPath);
13414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
13434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup() {
13474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getGroupName() {
13504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mGroupName;
13514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Matrix getLocalMatrix() {
13544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mLocalMatrix;
13554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1357d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) {
13584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(res, theme, attrs,
1359d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup);
1360d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
13614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
13624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1364d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
13654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
13664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
13674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
13694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
13704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1371d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1372d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation",
1373d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_rotation, mRotate);
1374d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1375d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mPivotX = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotX, mPivotX);
1376d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mPivotY = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotY, mPivotY);
1377d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1378d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1379d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX",
1380d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_scaleX, mScaleX);
1381d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1382d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1383d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY",
1384d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_scaleY, mScaleY);
1385d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1386d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX",
1387d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_translateX, mTranslateX);
1388d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY",
1389d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_translateY, mTranslateY);
13904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String groupName =
13929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableGroup_name);
13934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (groupName != null) {
13944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mGroupName = groupName;
13954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateLocalMatrix();
13984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateLocalMatrix() {
14014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The order we apply is the same as the
14024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
14034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.reset();
14044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
14054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
14064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
14074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
14084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
14114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getRotation() {
14134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRotate;
14144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRotation(float rotation) {
14184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (rotation != mRotate) {
14194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRotate = rotation;
14204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotX() {
14264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotX;
14274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotX(float pivotX) {
14314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotX != mPivotX) {
14324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotX = pivotX;
14334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotY() {
14394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotY;
14404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotY(float pivotY) {
14444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotY != mPivotY) {
14454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotY = pivotY;
14464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleX() {
14524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleX;
14534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleX(float scaleX) {
14574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleX != mScaleX) {
14584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleX = scaleX;
14594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleY() {
14654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleY;
14664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleY(float scaleY) {
14704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleY != mScaleY) {
14714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleY = scaleY;
14724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateX() {
14784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateX;
14794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateX(float translateX) {
14834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateX != mTranslateX) {
14844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateX = translateX;
14854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateY() {
14914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateY;
14924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateY(float translateY) {
14964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateY != mTranslateY) {
14974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateY = translateY;
14984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Common Path information for clip path and normal path.
15054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPath {
15074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        protected PathParser.PathDataNode[] mNodes = null;
15084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mPathName;
15094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
15104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath() {
15124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1515d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void printVPath(int level) {
1516d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String indent = "";
1517d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < level; i++) {
1518d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                indent += "    ";
1519d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1520d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            Log.v(LOGTAG, indent + "current path is :" + mPathName +
1521d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    " pathData is " + NodesToString(mNodes));
1522d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1523d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1524d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1525d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public String NodesToString(PathParser.PathDataNode[] nodes) {
1526d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String result = " ";
1527d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < nodes.length; i++) {
1528d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                result += nodes[i].type + ":";
1529d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                float[] params = nodes[i].params;
1530d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                for (int j = 0; j < params.length; j++) {
1531d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    result += params[j] + ",";
1532d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                }
1533d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1534d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            return result;
1535d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1536d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
15374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath(VPath copy) {
15384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPathName = copy.mPathName;
15394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
15404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
15414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void toPath(Path path) {
15444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            path.reset();
15454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mNodes != null) {
15464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
15474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getPathName() {
15514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPathName;
15524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
15554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
15594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
15624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
15664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public PathParser.PathDataNode[] getPathData() {
15684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mNodes;
15694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
15734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
15744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // This should not happen in the middle of animation.
15754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.deepCopyNodes(nodes);
15764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
15774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.updateNodes(mNodes, nodes);
15784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Clip path, which only has name and pathData.
15844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VClipPath extends VPath {
15864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath() {
15874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath(VClipPath copy) {
15914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
15924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1594d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
15954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // TODO TINT THEME Not supported yet
1596d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1597d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
1598d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1599d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
16004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1601d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableClipPath);
16024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateStateFromTypedArray(a);
16034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
16044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateStateFromTypedArray(TypedArray a) {
16074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
16084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
16094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathName =
16119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableClipPath_name);
16124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
16134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
16144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
16179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableClipPath_pathData);
16184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
16194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
16204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
16244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
16254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
16264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
16284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
16304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Normal path, which contains all the fill / paint information.
16314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
16324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VFullPath extends VPath {
16334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
16344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
16354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
16364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mStrokeColor = Color.TRANSPARENT;
16384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeWidth = 0;
16394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillColor = Color.TRANSPARENT;
16414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeAlpha = 1.0f;
16424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillRule;
16434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mFillAlpha = 1.0f;
16444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathStart = 0;
16454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathEnd = 1;
16464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathOffset = 0;
16474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
16494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
16504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeMiterlimit = 4;
16514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath() {
16534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
16544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath(VFullPath copy) {
16574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
16584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
16594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = copy.mStrokeColor;
16614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = copy.mStrokeWidth;
16624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = copy.mStrokeAlpha;
16634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = copy.mFillColor;
16644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillRule = copy.mFillRule;
16654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = copy.mFillAlpha;
16664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = copy.mTrimPathStart;
16674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = copy.mTrimPathEnd;
16684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = copy.mTrimPathOffset;
16694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineCap = copy.mStrokeLineCap;
16714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
16724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
16734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
16764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
16774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_BUTT:
16784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.BUTT;
16794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_ROUND:
16804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.ROUND;
16814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_SQUARE:
16824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.SQUARE;
16834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
16844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
16854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
16894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
16904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_MITER:
16914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.MITER;
16924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_ROUND:
16934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.ROUND;
16944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_BEVEL:
16954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.BEVEL;
16964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
16974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
16984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
17034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mThemeAttrs != null;
17044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1706d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
17074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1708d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath);
1709d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
17104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
17114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1713d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
17144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
17154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
17164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
17184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
17194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // In order to work around the conflicting id issue, we need to double check the
17219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // existence of the attribute.
17229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // B/c if the attribute existed in the compiled XML, then calling TypedArray will be
17239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // safe since the framework will look up in the XML first.
17249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay.
1725d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1726d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
17279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // If there is no pathData in the <path> tag, then this is an empty path,
17289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // nothing need to be drawn.
1729d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1730d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1731d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1732d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final String pathName = a.getString(AndroidResources.styleable_VectorDrawablePath_name);
17334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
17344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
17354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
17379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawablePath_pathData);
17384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
17394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
17404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1742d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor",
1743d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_fillColor, mFillColor);
17442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "fillAlpha",
1745d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_fillAlpha, mFillAlpha);
1746d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap",
1747d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeLineCap, -1);
1748d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap);
1749d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin",
1750d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeLineJoin, -1);
1751d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin);
1752d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit",
17539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeMiterLimit,
17549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    mStrokeMiterlimit);
1755d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor",
1756d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeColor, mStrokeColor);
1757d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha",
1758d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeAlpha, mStrokeAlpha);
1759d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth",
1760d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeWidth, mStrokeWidth);
1761d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd",
1762d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathEnd, mTrimPathEnd);
1763d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset",
1764d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathOffset, mTrimPathOffset);
1765d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart",
1766d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathStart, mTrimPathStart);
17674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
17714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mThemeAttrs == null) {
17724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return;
17734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            /*
17764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * TODO TINT THEME Not supported yet final TypedArray a =
1777d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu             * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath);
17784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * updateStateFromTypedArray(a); a.recycle();
17794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             */
17804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
17834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getStrokeColor() {
17854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeColor;
17864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeColor(int strokeColor) {
17904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = strokeColor;
17914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeWidth() {
17954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeWidth;
17964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeWidth(float strokeWidth) {
18004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = strokeWidth;
18014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeAlpha() {
18054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeAlpha;
18064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeAlpha(float strokeAlpha) {
18104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = strokeAlpha;
18114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getFillColor() {
18154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillColor;
18164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillColor(int fillColor) {
18204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = fillColor;
18214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getFillAlpha() {
18254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillAlpha;
18264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillAlpha(float fillAlpha) {
18304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = fillAlpha;
18314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathStart() {
18354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathStart;
18364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathStart(float trimPathStart) {
18404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = trimPathStart;
18414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathEnd() {
18454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathEnd;
18464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathEnd(float trimPathEnd) {
18504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = trimPathEnd;
18514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathOffset() {
18554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathOffset;
18564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathOffset(float trimPathOffset) {
18604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = trimPathOffset;
18614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
18634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui}
1864