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
178e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
18e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.ColorStateList;
204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources;
214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources.Theme;
224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.TypedArray;
234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Bitmap;
244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Canvas;
254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Color;
264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.ColorFilter;
274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Matrix;
284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Paint;
294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Path;
304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PathMeasure;
314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PixelFormat;
324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff;
334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff.Mode;
344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuffColorFilter;
354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Rect;
364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.drawable.Drawable;
379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.graphics.drawable.VectorDrawable;
389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.os.Build;
39968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhuimport android.support.annotation.DrawableRes;
404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.NonNull;
414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.Nullable;
42b6086751979cb14740815502597e9fcfddb7054aztenghuiimport android.support.annotation.RequiresApi;
4367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.annotation.RestrictTo;
4467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.content.res.ResourcesCompat;
45a80878dec1a3689e6e79566a9650de39c3291c01Yuichi Arakiimport android.support.v4.content.res.TypedArrayUtils;
46142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Arakiimport android.support.v4.graphics.PathParser;
4767b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.graphics.drawable.DrawableCompat;
484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.v4.util.ArrayMap;
494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.AttributeSet;
500327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhuimport android.util.LayoutDirection;
514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Log;
524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Xml;
534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
54b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParser;
55b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParserException;
56b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hirono
574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.io.IOException;
584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.ArrayList;
594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.Stack;
604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/**
62c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
63ab9d2bf6fe28ff4a95985526daa128239c03d821Teng-Hui Zhu * For older API version, this class lets you create a drawable based on an XML vector graphic.
6495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
657c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API.
667c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * In order to refer to VectorDrawableCompat inside a XML file,  you can use app:srcCompat attribute
677c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * in AppCompat library's ImageButton or ImageView.
6895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
6995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <strong>Note:</strong> To optimize for the re-drawing performance, one bitmap cache is created
7095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * for each VectorDrawableCompat. Therefore, referring to the same VectorDrawableCompat means
7195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * sharing the same bitmap cache. If these references don't agree upon on the same size, the bitmap
7295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * will be recreated and redrawn every time size is changed. In other words, if a VectorDrawable is
7395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * used for different sizes, it is more efficient to create multiple VectorDrawables, one for each
7495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * size.
7595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * VectorDrawableCompat can be defined in an XML file with the <code>&lt;vector></code> element.
7795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The VectorDrawableCompat has the following elements:
7995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
8095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;vector></code></dt>
8195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define a vector drawable
8395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
8595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of this vector drawable.</dd>
8695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:width</code></dt>
8795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic width of the drawable.
8895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
8995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:height</code></dt>
9095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic height the drawable.
9195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
9295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportWidth</code></dt>
9395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the width of the viewport space. Viewport is basically
9495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportHeight</code></dt>
9695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the height of the viewport space. Viewport is basically
9795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tint</code></dt>
9995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
10095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tintMode</code></dt>
101791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd>
10295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:autoMirrored</code></dt>
10395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
104791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * RTL (right-to-left). Default is false.</dd>
10595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:alpha</code></dt>
106791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of this drawable. Default is 1.</dd>
10795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
10895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
10995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
11095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
11195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;group></code></dt>
11295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines a group of paths or subgroups, plus transformation information.
11395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The transformations are defined in the same coordinates as the viewport.
11495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * And the transformations are applied in the order of scale, rotate then translate.
11595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
11695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
11795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the group.</dd>
11895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:rotation</code></dt>
119791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The degrees of rotation of the group. Default is 0.</dd>
12095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotX</code></dt>
12195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The X coordinate of the pivot for the scale and rotation of the group.
122791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotY</code></dt>
12495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
125791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleX</code></dt>
127791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the X Coordinate. Default is 1.</dd>
12895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleY</code></dt>
129791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the Y coordinate. Default is 1.</dd>
13095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateX</code></dt>
13195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the X coordinate.
132791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateY</code></dt>
13495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the Y coordinate.
135791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
13795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
13895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
13995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
14095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;path></code></dt>
14195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines paths to be drawn.
14295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
14395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
14495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the path.</dd>
14595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
14695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path data using exactly same format as "d" attribute
14795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data. This is defined in the viewport space.</dd>
14895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillColor</code></dt>
14995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to fill the path.
15095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
15195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path fill is drawn if this property is not specified.</dd>
15295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeColor</code></dt>
15395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to draw the path outline.
15495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
15595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path outline is drawn if this property is not specified.</dd>
15695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeWidth</code></dt>
157791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The width a path stroke. Default is 0.</dd>
15895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeAlpha</code></dt>
159791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of a path stroke. Default is 1.</dd>
16095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillAlpha</code></dt>
161791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity to fill the path with. Default is 1.</dd>
16295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathStart</code></dt>
163791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd>
16495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathEnd</code></dt>
165791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd>
16695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathOffset</code></dt>
16795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Shift trim region (allows showed region to include the start and end), in the range
168791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * from 0 to 1. Default is 0.</dd>
16995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineCap</code></dt>
170791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd>
17195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineJoin</code></dt>
172791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
17395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeMiterLimit</code></dt>
174791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
17595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
17695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
17795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
17895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
17995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;clip-path></code></dt>
18095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path to be the current clip. Note that the clip path only apply to
18195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the current group and its children.
18295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
18395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
18495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the clip path.</dd>
18595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
18695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines clip path using the same format as "d" attribute
18795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data.</dd>
18895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
18995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
190791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <p/>
191791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * Note that theme attributes in XML file are supported through
192791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <code>{@link #inflate(Resources, XmlPullParser, AttributeSet, Theme)}</code>.
1934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
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() {
267c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        if (mDelegateDrawable != null && Build.VERSION.SDK_INT >= 24) {
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     */
5198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas    @RestrictTo(LIBRARY_GROUP)
5204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public float getPixelSize() {
521791777822ec5bd177f5c03655411486e150be6edztenghui        if (mVectorState == null || mVectorState.mVPathRenderer == null
52298ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mBaseWidth == 0
52398ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mBaseHeight == 0
52498ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mViewportHeight == 0
52598ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || 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
619b6086751979cb14740815502597e9fcfddb7054aztenghui        final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs,
620b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TYPE_ARRAY);
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:
64972da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                if (Build.VERSION.SDK_INT >= 11) {
65072da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                    return Mode.ADD;
65172da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                } else {
65272da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                    return defaultMode;
65372da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                }
6542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            default:
6552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return defaultMode;
656d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
657d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    }
658d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
6599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser)
6609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            throws XmlPullParserException {
6619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
6624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
6634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Account for any configuration changes.
6654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
6664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
667d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode",
668b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT_MODE, -1);
6696705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu        state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN);
6704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final ColorStateList tint =
672b6086751979cb14740815502597e9fcfddb7054aztenghui                a.getColorStateList(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT);
6734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint != null) {
6744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
6754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
677d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored",
678b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_AUTO_MIRRORED, state.mAutoMirrored);
679d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
680d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth",
681b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_WIDTH,
6829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportWidth);
6834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
684d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight",
685b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_HEIGHT,
6869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportHeight);
6874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mViewportWidth <= 0) {
6894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportWidth > 0");
6914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
6924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportHeight > 0");
6944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseWidth = a.getDimension(
697b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_WIDTH, pathRenderer.mBaseWidth);
6984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseHeight = a.getDimension(
699b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_HEIGHT, pathRenderer.mBaseHeight);
7004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mBaseWidth <= 0) {
7014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
7024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires width > 0");
7034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
7044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
7054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires height > 0");
7064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
708d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        // shown up from API 11.
709d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
710b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_ALPHA, pathRenderer.getAlpha());
7114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.setAlpha(alphaInFloat);
7124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
713b6086751979cb14740815502597e9fcfddb7054aztenghui        final String name = a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_NAME);
7144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (name != null) {
7154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mRootName = name;
7164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
7174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
7212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                 Theme theme) throws XmlPullParserException, IOException {
7229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
7234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
7244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean noPathTag = true;
7254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Use a stack to help to build the group tree.
7274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // The top of the stack is always the current group.
7284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
7294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        groupStack.push(pathRenderer.mRootGroup);
7304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int eventType = parser.getEventType();
73267b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        final int innerDepth = parser.getDepth() + 1;
73367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu
73467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        // Parse everything until the end of the vector element.
73567b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        while (eventType != XmlPullParser.END_DOCUMENT
73667b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
7374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (eventType == XmlPullParser.START_TAG) {
7384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final VGroup currentGroup = groupStack.peek();
7404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_PATH.equals(tagName)) {
7414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VFullPath path = new VFullPath();
742d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    noPathTag = false;
7484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
7504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VClipPath path = new VClipPath();
751d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
7584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup newChildGroup = new VGroup();
759d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    newChildGroup.inflate(res, attrs, theme, parser);
7604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(newChildGroup);
7614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.push(newChildGroup);
7624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newChildGroup.getGroupName() != null) {
7634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
7644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                                newChildGroup);
7654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
7674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
7694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_GROUP.equals(tagName)) {
7714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.pop();
7724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            eventType = parser.next();
7754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the tree out for debug.
7784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (DBG_VECTOR_DRAWABLE) {
7794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
7804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (noPathTag) {
7834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final StringBuffer tag = new StringBuffer();
7844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (tag.length() > 0) {
7864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                tag.append(" or ");
7874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            tag.append(SHAPE_PATH);
7894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException("no " + tag + " defined");
7914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
7954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String indent = "";
7964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < level; i++) {
7974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            indent += "    ";
7984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the current node
8004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
8014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                + " rotation is " + currentGroup.mRotate);
8024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
8034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Then print all the children groups
8044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
8054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Object child = currentGroup.mChildren.get(i);
8064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (child instanceof VGroup) {
8074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                printGroupTree((VGroup) child, level + 1);
808d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            } else {
809d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                ((VPath) child).printVPath(level + 1);
8104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    void setAllowCaching(boolean allowCaching) {
8154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mAllowCaching = allowCaching;
8164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
8194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean needMirroring() {
820905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette        if (Build.VERSION.SDK_INT >= 17) {
8210327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
822905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette        } else {
823905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette            return false;
8240327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
8254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // Extra override functions for delegation for SDK >= 7.
8289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8295f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu    protected void onBoundsChange(Rect bounds) {
8309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8315f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu            mDelegateDrawable.setBounds(bounds);
8329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public int getChangingConfigurations() {
8379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getChangingConfigurations();
8399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
8419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void invalidateSelf() {
8459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8469f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.invalidateSelf();
8479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.invalidateSelf();
8509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void scheduleSelf(Runnable what, long when) {
8549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.scheduleSelf(what, when);
8569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.scheduleSelf(what, when);
8599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public boolean setVisible(boolean visible, boolean restart) {
8639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setVisible(visible, restart);
8659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        return super.setVisible(visible, restart);
8679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void unscheduleSelf(Runnable what) {
8719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.unscheduleSelf(what);
8739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.unscheduleSelf(what);
8769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    /**
879c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu     * Constant state for delegating the creating drawable job for SDK >= 24.
8809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains
8819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * a delegated VectorDrawable instance.
8829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     */
883c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(24)
8849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableDelegateState extends ConstantState {
8859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        private final ConstantState mDelegateState;
8862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
8879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableDelegateState(ConstantState state) {
8889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateState = state;
8899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
8929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable() {
8939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
8949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable();
8959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
8969f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
8999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res) {
9009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(res);
9029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res, Theme theme) {
9079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable =
9099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    (VectorDrawable) mDelegateState.newDrawable(res, theme);
9109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public boolean canApplyTheme() {
9159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.canApplyTheme();
9169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public int getChangingConfigurations() {
9209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.getChangingConfigurations();
9219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
9239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableCompatState extends ConstantState {
9254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
9264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        VPathRenderer mVPathRenderer;
9274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mTint = null;
9284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mTintMode = DEFAULT_TINT_MODE;
9294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mAutoMirrored;
9304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Bitmap mCachedBitmap;
9324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int[] mCachedThemeAttrs;
9334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mCachedTint;
9344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mCachedTintMode;
9354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mCachedRootAlpha;
9364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCachedAutoMirrored;
9374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCacheDirty;
9384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        /**
9402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         * Temporary paint object used to draw cached bitmaps.
9412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         */
9424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint mTempPaint;
9434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Deep copy for mutate() or implicitly mutate.
9459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState(VectorDrawableCompatState copy) {
9464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy != null) {
9474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mChangingConfigurations = copy.mChangingConfigurations;
9484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
9494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mFillPaint != null) {
9504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
9514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mStrokePaint != null) {
9534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
9544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTint = copy.mTint;
9564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTintMode = copy.mTintMode;
9574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mAutoMirrored = copy.mAutoMirrored;
9584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9611f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
9621f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                                                  Rect originalBounds) {
9634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The bitmap's size is the same as the bounds.
9644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Paint p = getPaint(filter);
9651f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
9664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean hasTranslucentRoot() {
9694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mVPathRenderer.getRootAlpha() < 255;
9704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /**
9734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * @return null when there is no need for alpha paint.
9744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
9754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Paint getPaint(ColorFilter filter) {
9764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!hasTranslucentRoot() && filter == null) {
9774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return null;
9784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mTempPaint == null) {
9814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint = new Paint();
9824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint.setFilterBitmap(true);
9834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
9854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setColorFilter(filter);
9864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTempPaint;
9874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void updateCachedBitmap(int width, int height) {
9904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
9914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
9921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVPathRenderer.draw(tmpCanvas, width, height, null);
9934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void createCachedBitmapIfNeeded(int width, int height) {
9961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
9971f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mCachedBitmap = Bitmap.createBitmap(width, height,
9984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        Bitmap.Config.ARGB_8888);
9994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mCacheDirty = true;
10004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseBitmap(int width, int height) {
10054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (width == mCachedBitmap.getWidth()
10064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && height == mCachedBitmap.getHeight()) {
10074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseCache() {
10134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mCacheDirty
10144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTint == mTint
10154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTintMode == mTintMode
10164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedAutoMirrored == mAutoMirrored
10174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
10184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void updateCacheStates() {
10244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
10254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // likely hit cache miss more, but practically not much difference.
10264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTint = mTint;
10274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTintMode = mTintMode;
10284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
10294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedAutoMirrored = mAutoMirrored;
10304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCacheDirty = false;
10314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState() {
10344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVPathRenderer = new VPathRenderer();
10354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable() {
10394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable(Resources res) {
10444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getChangingConfigurations() {
10494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mChangingConfigurations;
10504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
10524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPathRenderer {
10544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Right now the internal data structure is organized as a tree.
10554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * Each node can be a group node, or a path.
10564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * A group node can have groups or paths as children, but a path node has
10574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * no children.
10584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * One example can be:
10594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                 Root Group
10604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                /    |     \
10614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *           Group    Path    Group
10624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *          /     \             |
10634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *         Path   Path         Path
10644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *
10654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
10664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables that only used temporarily inside the draw() call, so there
10674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // is no need for deep copying.
10684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mPath;
10694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mRenderPath;
10704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
10714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mFinalPathMatrix = new Matrix();
10724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mStrokePaint;
10744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mFillPaint;
10754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private PathMeasure mPathMeasure;
10764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
10784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
10794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int mChangingConfigurations;
10808fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        final VGroup mRootGroup;
10814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseWidth = 0;
10824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseHeight = 0;
10834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportWidth = 0;
10844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportHeight = 0;
10854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mRootAlpha = 0xFF;
10864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mRootName = null;
10874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
10894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer() {
10914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup();
10924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path();
10934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path();
10944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRootAlpha(int alpha) {
10974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = alpha;
10984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getRootAlpha() {
11014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRootAlpha;
11024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
11054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Animator like to use alpha from 0 to 1.
11064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setAlpha(float alpha) {
11074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            setRootAlpha((int) (alpha * 255));
11084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
11114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getAlpha() {
11124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return getRootAlpha() / 255.0f;
11134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer(VPathRenderer copy) {
11164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
11174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path(copy.mPath);
11184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path(copy.mRenderPath);
11194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseWidth = copy.mBaseWidth;
11204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseHeight = copy.mBaseHeight;
11214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportWidth = copy.mViewportWidth;
11224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportHeight = copy.mViewportHeight;
11234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
11244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = copy.mRootAlpha;
11254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootName = copy.mRootName;
11264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy.mRootName != null) {
11274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVGTargetsMap.put(copy.mRootName, this);
11284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
11294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
11322c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                   Canvas canvas, int w, int h, ColorFilter filter) {
11334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Calculate current group's matrix by preConcat the parent's and
11344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // and the current one on the top of the stack.
11354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
11364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Mi the local matrix at level i of the group tree.
11374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
11384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
11404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
114104027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            // Save the current clip information, which is local to this group.
114204027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.save();
114304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
11444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Draw the group tree in the same order as the XML file.
11454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
11464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object child = currentGroup.mChildren.get(i);
11474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (child instanceof VGroup) {
11484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup childGroup = (VGroup) child;
11494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
11504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                            canvas, w, h, filter);
11514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (child instanceof VPath) {
11524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath childPath = (VPath) child;
11534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawPath(currentGroup, childPath, canvas, w, h, filter);
11544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
11554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
115604027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
115704027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.restore();
11584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
1161c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas            // Traverse the tree in pre-order to draw.
11624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
11634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
11662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                              ColorFilter filter) {
11674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleX = w / mViewportWidth;
11684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleY = h / mViewportHeight;
11694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float minScale = Math.min(scaleX, scaleY);
11702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
11714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFinalPathMatrix.set(groupStackedMatrix);
11734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
11744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final float matrixScale = getMatrixScale(groupStackedMatrix);
11772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (matrixScale == 0) {
11782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                // When either x or y is scaled to 0, we don't need to draw anything.
11792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return;
11802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
11814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            vPath.toPath(mPath);
11824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Path path = mPath;
11834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath.reset();
11854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (vPath.isClipPath()) {
11874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
118804027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu                canvas.clipPath(mRenderPath);
11894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
11904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                VFullPath fullPath = (VFullPath) vPath;
11914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
11924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
11934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
11944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mPathMeasure == null) {
11964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure = new PathMeasure();
11974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
11984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mPathMeasure.setPath(mPath, false);
11994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float len = mPathMeasure.getLength();
12014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    start = start * len;
12024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    end = end * len;
12034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.reset();
12044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (start > end) {
12054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, len, path, true);
12064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(0f, end, path, true);
12074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
12084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, end, path, true);
12094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.rLineTo(0, 0); // fix bug in measure
12114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
12134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
12154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mFillPaint == null) {
12164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint = new Paint();
12174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
12184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setAntiAlias(true);
12194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint fillPaint = mFillPaint;
12224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
12234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColorFilter(filter);
1224401033a37f69a78f27f748c3ef95e7291e1339ffztenghui                    mRenderPath.setFillType(fullPath.mFillRule == 0 ? Path.FillType.WINDING
1225401033a37f69a78f27f748c3ef95e7291e1339ffztenghui                            : Path.FillType.EVEN_ODD);
12264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, fillPaint);
12274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
12304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mStrokePaint == null) {
12314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint = new Paint();
12324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
12334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setAntiAlias(true);
12344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint strokePaint = mStrokePaint;
12374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineJoin != null) {
12384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
12394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineCap != null) {
12424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
12434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
12464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
12474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColorFilter(filter);
12482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    final float finalStrokeScale = minScale * matrixScale;
12492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
12504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
12514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private static float cross(float v1x, float v1y, float v2x, float v2y) {
12562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return v1x * v2y - v1y * v2x;
12572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private float getMatrixScale(Matrix groupStackedMatrix) {
12602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Given unit vectors A = (0, 1) and B = (1, 0).
12612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
12622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
12632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
12642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
12652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            //
12662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
12672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // scale on x and y axis, and take the minimal of these two.
12682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For skew case, an unit square will mapped to a parallelogram. And this function will
12692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // return the minimal height of the 2 bases.
12702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float[] unitVectors = new float[]{0, 1, 1, 0};
12712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            groupStackedMatrix.mapVectors(unitVectors);
12722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]);
12732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]);
12742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2],
12752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    unitVectors[3]);
12762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float maxScale = Math.max(scaleX, scaleY);
12772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float matrixScale = 0;
12792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (maxScale > 0) {
12802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                matrixScale = Math.abs(crossProduct) / maxScale;
12812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (DBG_VECTOR_DRAWABLE) {
12832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
12842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return matrixScale;
12862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
12884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VGroup {
12904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
12914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // the parents' local matrices with the current one.
12924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mStackedMatrix = new Matrix();
12934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
12954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
12964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
12974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12988fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        float mRotate = 0;
12994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotX = 0;
13004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotY = 0;
13014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleX = 1;
13024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleY = 1;
13034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateX = 0;
13044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateY = 0;
13054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mLocalMatrix is updated based on the update of transformation information,
13074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // either parsed from the XML or by animation.
13084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mLocalMatrix = new Matrix();
13098fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        int mChangingConfigurations;
13104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
13114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private String mGroupName = null;
13124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
13144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRotate = copy.mRotate;
13154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotX = copy.mPivotX;
13164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotY = copy.mPivotY;
13174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleX = copy.mScaleX;
13184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleY = copy.mScaleY;
13194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateX = copy.mTranslateX;
13204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateY = copy.mTranslateY;
13214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
13224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mGroupName = copy.mGroupName;
13234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
13244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mGroupName != null) {
13254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                targetsMap.put(mGroupName, this);
13264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.set(copy.mLocalMatrix);
13294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final ArrayList<Object> children = copy.mChildren;
13314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < children.size(); i++) {
13324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object copyChild = children.get(i);
13334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copyChild instanceof VGroup) {
13344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup copyGroup = (VGroup) copyChild;
13354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
13364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else {
13374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath newPath = null;
13384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (copyChild instanceof VFullPath) {
13394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VFullPath((VFullPath) copyChild);
13404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else if (copyChild instanceof VClipPath) {
13414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VClipPath((VClipPath) copyChild);
13424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
13434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        throw new IllegalStateException("Unknown object in the tree!");
13444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(newPath);
13464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newPath.mPathName != null) {
13474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        targetsMap.put(newPath.mPathName, newPath);
13484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
13504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup() {
13544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getGroupName() {
13574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mGroupName;
13584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Matrix getLocalMatrix() {
13614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mLocalMatrix;
13624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1364d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) {
1365b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs,
1366b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP);
1367d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
13684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
13694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1371d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
13724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
13734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
13744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
13764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
13774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1378d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1379d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation",
1380b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_ROTATION, mRotate);
1381d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1382b6086751979cb14740815502597e9fcfddb7054aztenghui            mPivotX = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_X, mPivotX);
1383b6086751979cb14740815502597e9fcfddb7054aztenghui            mPivotY = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_Y, mPivotY);
1384d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1385d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1386d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX",
1387b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_X, mScaleX);
1388d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1389d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1390d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY",
1391b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_Y, mScaleY);
1392d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1393d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX",
1394b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_X, mTranslateX);
1395d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY",
1396b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_Y, mTranslateY);
13974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String groupName =
1399b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_NAME);
14004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (groupName != null) {
14014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mGroupName = groupName;
14024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateLocalMatrix();
14054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateLocalMatrix() {
14084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The order we apply is the same as the
14094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
14104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.reset();
14114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
14124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
14134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
14144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
14154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
14184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getRotation() {
14204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRotate;
14214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRotation(float rotation) {
14254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (rotation != mRotate) {
14264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRotate = rotation;
14274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotX() {
14334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotX;
14344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotX(float pivotX) {
14384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotX != mPivotX) {
14394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotX = pivotX;
14404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotY() {
14464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotY;
14474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotY(float pivotY) {
14514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotY != mPivotY) {
14524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotY = pivotY;
14534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleX() {
14594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleX;
14604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleX(float scaleX) {
14644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleX != mScaleX) {
14654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleX = scaleX;
14664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleY() {
14724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleY;
14734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleY(float scaleY) {
14774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleY != mScaleY) {
14784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleY = scaleY;
14794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateX() {
14854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateX;
14864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateX(float translateX) {
14904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateX != mTranslateX) {
14914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateX = translateX;
14924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateY() {
14984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateY;
14994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateY(float translateY) {
15034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateY != mTranslateY) {
15044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateY = translateY;
15054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
15064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Common Path information for clip path and normal path.
15124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPath {
15144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        protected PathParser.PathDataNode[] mNodes = null;
15154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mPathName;
15164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
15174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath() {
15194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1522d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void printVPath(int level) {
1523d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String indent = "";
1524d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < level; i++) {
1525d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                indent += "    ";
1526d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1527d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            Log.v(LOGTAG, indent + "current path is :" + mPathName +
1528b6086751979cb14740815502597e9fcfddb7054aztenghui                    " pathData is " + nodesToString(mNodes));
1529d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1530d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1531d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1532b6086751979cb14740815502597e9fcfddb7054aztenghui        public String nodesToString(PathParser.PathDataNode[] nodes) {
1533d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String result = " ";
1534d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < nodes.length; i++) {
1535b6086751979cb14740815502597e9fcfddb7054aztenghui                result += nodes[i].mType + ":";
1536b6086751979cb14740815502597e9fcfddb7054aztenghui                float[] params = nodes[i].mParams;
1537d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                for (int j = 0; j < params.length; j++) {
1538d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    result += params[j] + ",";
1539d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                }
1540d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1541d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            return result;
1542d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1543d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
15444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath(VPath copy) {
15454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPathName = copy.mPathName;
15464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
15474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
15484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void toPath(Path path) {
15514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            path.reset();
15524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mNodes != null) {
15534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
15544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getPathName() {
15584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPathName;
15594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
15624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
15664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
15694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
15734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public PathParser.PathDataNode[] getPathData() {
15754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mNodes;
15764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
15804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
15814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // This should not happen in the middle of animation.
15824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.deepCopyNodes(nodes);
15834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
15844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.updateNodes(mNodes, nodes);
15854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Clip path, which only has name and pathData.
15914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VClipPath extends VPath {
15934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath() {
15944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath(VClipPath copy) {
15984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
15994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1601d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
16024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // TODO TINT THEME Not supported yet
1603d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1604d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
1605d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1606d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1607b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs,
1608b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH);
16094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateStateFromTypedArray(a);
16104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
16114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateStateFromTypedArray(TypedArray a) {
16144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
16154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
16164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathName =
1618b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_NAME);
16194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
16204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
16214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
1624b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_PATH_DATA);
16254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
16264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
16274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
16314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
16324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
16334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
16354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
16374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Normal path, which contains all the fill / paint information.
16384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
16394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VFullPath extends VPath {
16404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
16414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
16424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
16434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mStrokeColor = Color.TRANSPARENT;
16454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeWidth = 0;
16464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillColor = Color.TRANSPARENT;
16484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeAlpha = 1.0f;
1649401033a37f69a78f27f748c3ef95e7291e1339ffztenghui        int mFillRule = 0; // 0 is default value as "non-zero" fill type.
16504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mFillAlpha = 1.0f;
16514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathStart = 0;
16524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathEnd = 1;
16534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathOffset = 0;
16544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
16564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
16574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeMiterlimit = 4;
16584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath() {
16604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
16614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath(VFullPath copy) {
16644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
16654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
16664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = copy.mStrokeColor;
16684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = copy.mStrokeWidth;
16694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = copy.mStrokeAlpha;
16704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = copy.mFillColor;
16714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillRule = copy.mFillRule;
16724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = copy.mFillAlpha;
16734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = copy.mTrimPathStart;
16744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = copy.mTrimPathEnd;
16754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = copy.mTrimPathOffset;
16764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineCap = copy.mStrokeLineCap;
16784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
16794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
16804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
16834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
16844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_BUTT:
16854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.BUTT;
16864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_ROUND:
16874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.ROUND;
16884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_SQUARE:
16894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.SQUARE;
16904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
16914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
16924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
16964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
16974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_MITER:
16984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.MITER;
16994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_ROUND:
17004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.ROUND;
17014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_BEVEL:
17024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.BEVEL;
17034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
17044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
17054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
17104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mThemeAttrs != null;
17114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1713d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
1714b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs,
1715b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH);
1716d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
17174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
17184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1720d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
17214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
17224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
17234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
17254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
17264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // In order to work around the conflicting id issue, we need to double check the
17289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // existence of the attribute.
17299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // B/c if the attribute existed in the compiled XML, then calling TypedArray will be
17309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // safe since the framework will look up in the XML first.
17319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay.
1732d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1733d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
17349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // If there is no pathData in the <path> tag, then this is an empty path,
17359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // nothing need to be drawn.
1736d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1737d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1738d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1739b6086751979cb14740815502597e9fcfddb7054aztenghui            final String pathName = a.getString(
1740b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_NAME);
17414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
17424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
17434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
1745b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_PATH_DATA);
17464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
17474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
17484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1750d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor",
1751b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_COLOR, mFillColor);
17522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "fillAlpha",
1753b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_ALPHA, mFillAlpha);
1754d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap",
1755b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_CAP, -1);
1756d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap);
1757d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin",
1758b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_JOIN, -1);
1759d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin);
1760d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit",
1761b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_MITER_LIMIT,
17629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    mStrokeMiterlimit);
1763d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor",
1764b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_COLOR, mStrokeColor);
1765d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha",
1766b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_ALPHA, mStrokeAlpha);
1767d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth",
1768b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_WIDTH, mStrokeWidth);
1769d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd",
1770b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_END, mTrimPathEnd);
1771d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset",
1772b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_OFFSET,
1773b6086751979cb14740815502597e9fcfddb7054aztenghui                    mTrimPathOffset);
1774d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart",
1775b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_START,
1776b6086751979cb14740815502597e9fcfddb7054aztenghui                    mTrimPathStart);
1777401033a37f69a78f27f748c3ef95e7291e1339ffztenghui            mFillRule = TypedArrayUtils.getNamedInt(a, parser, "fillType",
1778401033a37f69a78f27f748c3ef95e7291e1339ffztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_FILLTYPE,
1779401033a37f69a78f27f748c3ef95e7291e1339ffztenghui                    mFillRule);
17804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
17844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mThemeAttrs == null) {
17854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return;
17864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            /*
17894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * TODO TINT THEME Not supported yet final TypedArray a =
1790d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu             * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath);
17914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * updateStateFromTypedArray(a); a.recycle();
17924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             */
17934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
17964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getStrokeColor() {
17984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeColor;
17994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeColor(int strokeColor) {
18034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = strokeColor;
18044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeWidth() {
18084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeWidth;
18094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeWidth(float strokeWidth) {
18134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = strokeWidth;
18144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeAlpha() {
18184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeAlpha;
18194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeAlpha(float strokeAlpha) {
18234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = strokeAlpha;
18244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getFillColor() {
18284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillColor;
18294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillColor(int fillColor) {
18334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = fillColor;
18344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getFillAlpha() {
18384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillAlpha;
18394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillAlpha(float fillAlpha) {
18434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = fillAlpha;
18444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathStart() {
18484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathStart;
18494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathStart(float trimPathStart) {
18534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = trimPathStart;
18544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathEnd() {
18584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathEnd;
18594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathEnd(float trimPathEnd) {
18634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = trimPathEnd;
18644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathOffset() {
18684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathOffset;
18694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathOffset(float trimPathOffset) {
18734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = trimPathOffset;
18744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
18764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui}
1877