VectorDrawableCompat.java revision 98ec0d5b378c8417156037af6389e90f0074a26e
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
19af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viveretteimport android.annotation.SuppressLint;
204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.ColorStateList;
214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources;
224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources.Theme;
234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.TypedArray;
244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Bitmap;
254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Canvas;
264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Color;
274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.ColorFilter;
284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Matrix;
294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Paint;
304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Path;
314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PathMeasure;
324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PixelFormat;
334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff;
344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff.Mode;
354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuffColorFilter;
364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Rect;
374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.drawable.Drawable;
389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.graphics.drawable.VectorDrawable;
399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.os.Build;
40968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhuimport android.support.annotation.DrawableRes;
414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.NonNull;
424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.Nullable;
43b6086751979cb14740815502597e9fcfddb7054aztenghuiimport android.support.annotation.RequiresApi;
4467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.annotation.RestrictTo;
4567b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.content.res.ResourcesCompat;
46a80878dec1a3689e6e79566a9650de39c3291c01Yuichi Arakiimport android.support.v4.content.res.TypedArrayUtils;
47142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Arakiimport android.support.v4.graphics.PathParser;
4867b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.graphics.drawable.DrawableCompat;
494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.v4.util.ArrayMap;
504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.AttributeSet;
510327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhuimport android.util.LayoutDirection;
524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Log;
534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Xml;
544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
55b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParser;
56b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParserException;
57b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hirono
584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.io.IOException;
594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.ArrayList;
604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.Stack;
614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/**
63c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
64ab9d2bf6fe28ff4a95985526daa128239c03d821Teng-Hui Zhu * For older API version, this class lets you create a drawable based on an XML vector graphic.
6595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
667c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API.
677c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * In order to refer to VectorDrawableCompat inside a XML file,  you can use app:srcCompat attribute
687c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * in AppCompat library's ImageButton or ImageView.
6995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <strong>Note:</strong> To optimize for the re-drawing performance, one bitmap cache is created
7195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * for each VectorDrawableCompat. Therefore, referring to the same VectorDrawableCompat means
7295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * sharing the same bitmap cache. If these references don't agree upon on the same size, the bitmap
7395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * will be recreated and redrawn every time size is changed. In other words, if a VectorDrawable is
7495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * used for different sizes, it is more efficient to create multiple VectorDrawables, one for each
7595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * size.
7695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * VectorDrawableCompat can be defined in an XML file with the <code>&lt;vector></code> element.
7895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
7995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The VectorDrawableCompat has the following elements:
8095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/>
8195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;vector></code></dt>
8295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define a vector drawable
8495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
8595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
8695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of this vector drawable.</dd>
8795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:width</code></dt>
8895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic width of the drawable.
8995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
9095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:height</code></dt>
9195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic height the drawable.
9295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd>
9395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportWidth</code></dt>
9495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the width of the viewport space. Viewport is basically
9595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportHeight</code></dt>
9795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the height of the viewport space. Viewport is basically
9895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd>
9995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tint</code></dt>
10095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd>
10195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tintMode</code></dt>
102791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd>
10395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:autoMirrored</code></dt>
10495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Indicates if the drawable needs to be mirrored when its layout direction is
105791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * RTL (right-to-left). Default is false.</dd>
10695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:alpha</code></dt>
107791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of this drawable. Default is 1.</dd>
10895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
10995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
11095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
11195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
11295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;group></code></dt>
11395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines a group of paths or subgroups, plus transformation information.
11495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The transformations are defined in the same coordinates as the viewport.
11595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * And the transformations are applied in the order of scale, rotate then translate.
11695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
11795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
11895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the group.</dd>
11995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:rotation</code></dt>
120791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The degrees of rotation of the group. Default is 0.</dd>
12195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotX</code></dt>
12295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The X coordinate of the pivot for the scale and rotation of the group.
123791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotY</code></dt>
12595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The Y coordinate of the pivot for the scale and rotation of the group.
126791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
12795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleX</code></dt>
128791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the X Coordinate. Default is 1.</dd>
12995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleY</code></dt>
130791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the Y coordinate. Default is 1.</dd>
13195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateX</code></dt>
13295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the X coordinate.
133791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateY</code></dt>
13595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the Y coordinate.
136791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd>
13795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
13895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
13995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
14095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
14195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;path></code></dt>
14295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines paths to be drawn.
14395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
14495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
14595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the path.</dd>
14695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
14795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path data using exactly same format as "d" attribute
14895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data. This is defined in the viewport space.</dd>
14995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillColor</code></dt>
15095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to fill the path.
15195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
15295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path fill is drawn if this property is not specified.</dd>
15395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeColor</code></dt>
15495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to draw the path outline.
15595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value.
15695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path outline is drawn if this property is not specified.</dd>
15795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeWidth</code></dt>
158791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The width a path stroke. Default is 0.</dd>
15995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeAlpha</code></dt>
160791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of a path stroke. Default is 1.</dd>
16195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillAlpha</code></dt>
162791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity to fill the path with. Default is 1.</dd>
16395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathStart</code></dt>
164791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd>
16595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathEnd</code></dt>
166791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd>
16795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathOffset</code></dt>
16895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Shift trim region (allows showed region to include the start and end), in the range
169791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * from 0 to 1. Default is 0.</dd>
17095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineCap</code></dt>
171791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd>
17295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineJoin</code></dt>
173791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd>
17495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeMiterLimit</code></dt>
175791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd>
17695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
17795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
17895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu *
17995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
18095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>&lt;clip-path></code></dt>
18195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path to be the current clip. Note that the clip path only apply to
18295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the current group and its children.
18395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl>
18495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt>
18595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the clip path.</dd>
18695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt>
18795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines clip path using the same format as "d" attribute
18895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data.</dd>
18995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd>
19095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl>
191791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <p/>
192791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * Note that theme attributes in XML file are supported through
193791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <code>{@link #inflate(Resources, XmlPullParser, AttributeSet, Theme)}</code>.
1944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
195968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhupublic class VectorDrawableCompat extends VectorDrawableCommon {
1964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final String LOGTAG = "VectorDrawableCompat";
1974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
1994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_CLIP_PATH = "clip-path";
2014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_GROUP = "group";
2024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_PATH = "path";
2034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_VECTOR = "vector";
2044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_BUTT = 0;
2064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_ROUND = 1;
2074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_SQUARE = 2;
2084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_MITER = 0;
2104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_ROUND = 1;
2114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_BEVEL = 2;
2124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Cap the bitmap size, such that it won't hurt the performance too much
2141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // and it won't crash due to a very large scale.
2151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // The drawable will look blurry above this size.
2161f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private static final int MAX_CACHED_BITMAP_SIZE = 2048;
2171f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
218d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    private static final boolean DBG_VECTOR_DRAWABLE = false;
2194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private VectorDrawableCompatState mVectorState;
2214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private PorterDuffColorFilter mTintFilter;
2234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private ColorFilter mColorFilter;
2244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mMutated;
2264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
2284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // caching the bitmap by default is allowed.
2294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mAllowCaching = true;
2304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // The Constant state associated with the <code>mDelegateDrawable</code>.
2329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private ConstantState mCachedConstantStateDelegate;
2339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2341f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Temp variable, only for saving "new" operation at the draw() time.
2351f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final float[] mTmpFloats = new float[9];
2361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Matrix mTmpMatrix = new Matrix();
2371f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Rect mTmpBounds = new Rect();
2381f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
2398fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat() {
2409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        mVectorState = new VectorDrawableCompatState();
2414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2438fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat(@NonNull VectorDrawableCompatState state) {
2444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState = state;
2454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
2464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public Drawable mutate() {
2509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.mutate();
2529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return this;
2539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mMutated && super.mutate() == this) {
2569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mVectorState = new VectorDrawableCompatState(mVectorState);
2574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mMutated = true;
2584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return this;
2604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    Object getTargetByName(String name) {
2634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
2644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public ConstantState getConstantState() {
268c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette        if (mDelegateDrawable != null && Build.VERSION.SDK_INT >= 24) {
2692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Such that the configuration can be refreshed.
2702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return new VectorDrawableDelegateState(mDelegateDrawable.getConstantState());
2719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
2734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState;
2744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void draw(Canvas canvas) {
2789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.draw(canvas);
2809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2821f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // We will offset the bounds for drawBitmap, so copyBounds() here instead
2831f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // of getBounds().
2841f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        copyBounds(mTmpBounds);
2851f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
2861f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            // Nothing to draw
2871f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            return;
2881f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
2899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Color filters always override tint filters.
2911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
2921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
2931f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // The imageView can scale the canvas in different ways, in order to
2941f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
2951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // size first. This bitmap size is determined by the bounds and the
2961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // canvas scale.
2971f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.getMatrix(mTmpMatrix);
2981f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpMatrix.getValues(mTmpFloats);
2991f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
3001f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
3011f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3021f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewX = Math.abs(mTmpFloats[Matrix.MSKEW_X]);
3031f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewY = Math.abs(mTmpFloats[Matrix.MSKEW_Y]);
3041f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3051f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // When there is any rotation / skew, then the scale value is not valid.
3061f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (canvasSkewX != 0 || canvasSkewY != 0) {
3071f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleX = 1.0f;
3081f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleY = 1.0f;
3091f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
3101f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3111f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
3121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
3131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
3141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
3151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
3161f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (scaledWidth <= 0 || scaledHeight <= 0) {
3174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return;
3184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int saveCount = canvas.save();
3211f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.translate(mTmpBounds.left, mTmpBounds.top);
3224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3231f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Handle RTL mirroring.
3241f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final boolean needMirroring = needMirroring();
3254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (needMirroring) {
3261f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.translate(mTmpBounds.width(), 0);
3274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            canvas.scale(-1.0f, 1.0f);
3284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3301f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // At this point, canvas has been translated to the right position.
3311f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // And we use this bound for the destination rect for the drawBitmap, so
3321f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // we offset to (0, 0);
3331f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpBounds.offsetTo(0, 0);
3344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3351f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
3364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mAllowCaching) {
3371f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
3384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else {
3394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mVectorState.canReuseCache()) {
3401f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
3414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.updateCacheStates();
3424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
3434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3441f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
3454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        canvas.restoreToCount(saveCount);
3464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
34815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
3494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getAlpha() {
3509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
351ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompat.getAlpha(mDelegateDrawable);
3529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
3554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setAlpha(int alpha) {
3599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setAlpha(alpha);
3619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
3629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
3654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
3664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
3674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setColorFilter(ColorFilter colorFilter) {
3729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setColorFilter(colorFilter);
3749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
3759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mColorFilter = colorFilter;
3784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        invalidateSelf();
3794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
3824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Ensures the tint filter is consistent with the current tint color and
3834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * mode.
3844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
3854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
3862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                           PorterDuff.Mode tintMode) {
3874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint == null || tintMode == null) {
3884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return null;
3894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7.
3914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Therefore we create a new one all the time here. Don't expect this is called often.
3924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
3934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return new PorterDuffColorFilter(color, tintMode);
3944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
396af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viverette    @SuppressLint("NewApi")
39715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
3984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTint(int tint) {
3999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
400ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTint(mDelegateDrawable, tint);
4019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        setTintList(ColorStateList.valueOf(tint));
4054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
40715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintList(ColorStateList tint) {
4099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
410ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintList(mDelegateDrawable, tint);
4119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != tint) {
4164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
4174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
4184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
42215375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintMode(Mode tintMode) {
4249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
425ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintMode(mDelegateDrawable, tintMode);
4269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTintMode != tintMode) {
4314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTintMode = tintMode;
4324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
4334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean isStateful() {
4399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.isStateful();
4419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
4444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                && mVectorState.mTint.isStateful());
4454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    protected boolean onStateChange(int[] stateSet) {
4499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setState(stateSet);
4519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != null && state.mTintMode != null) {
4559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
4564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
4574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
4584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
4604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getOpacity() {
4649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getOpacity();
4669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return PixelFormat.TRANSLUCENT;
4694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicWidth() {
4739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicWidth();
4759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
4784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicHeight() {
4829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicHeight();
4849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
4874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // Don't support re-applying themes. The initial theme loading is working.
49015375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean canApplyTheme() {
4929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
493ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.canApplyTheme(mDelegateDrawable);
4949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
4974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4990327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    @Override
5000327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    public boolean isAutoMirrored() {
5010327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (mDelegateDrawable != null) {
5020327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return DrawableCompat.isAutoMirrored(mDelegateDrawable);
5030327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
5040327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        return mVectorState.mAutoMirrored;
5050327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    }
5060327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu
5070327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    @Override
5080327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    public void setAutoMirrored(boolean mirrored) {
5090327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (mDelegateDrawable != null) {
5100327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            DrawableCompat.setAutoMirrored(mDelegateDrawable, mirrored);
5110327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return;
5120327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
5130327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        mVectorState.mAutoMirrored = mirrored;
5140327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu    }
5154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
5164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This
5174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * is used to calculate the path animation accuracy.
5184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
5194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @hide
5204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
5218e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas    @RestrictTo(LIBRARY_GROUP)
5224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public float getPixelSize() {
52398ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas        if ((mVectorState == null && mVectorState.mVPathRenderer == null)
52498ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mBaseWidth == 0
52598ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mBaseHeight == 0
52698ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mViewportHeight == 0
52798ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas                || mVectorState.mVPathRenderer.mViewportWidth == 0) {
5284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return 1; // fall back to 1:1 pixel mapping.
5294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
5314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
5324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
5334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
5344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleX = viewportWidth / intrinsicWidth;
5354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleY = viewportHeight / intrinsicHeight;
5364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return Math.min(scaleX, scaleY);
5374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
5404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Create a VectorDrawableCompat object.
5414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
5422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu     * @param res   the resources.
5434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param resId the resource ID for VectorDrawableCompat object.
5444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param theme the theme of this vector drawable, it can be null.
5454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @return a new VectorDrawableCompat or null if parsing error is found.
5464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
547af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viverette    @SuppressLint("NewApi")
5484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Nullable
5494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId,
5502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                              @Nullable Theme theme) {
551c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu        if (Build.VERSION.SDK_INT >= 24) {
5529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final VectorDrawableCompat drawable = new VectorDrawableCompat();
553ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            drawable.mDelegateDrawable = ResourcesCompat.getDrawable(res, resId, theme);
5542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            drawable.mCachedConstantStateDelegate = new VectorDrawableDelegateState(
5552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    drawable.mDelegateDrawable.getConstantState());
5569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawable;
5579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
5589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
5594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        try {
5604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final XmlPullParser parser = res.getXml(resId);
5614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final AttributeSet attrs = Xml.asAttributeSet(parser);
5624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            int type;
5634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            while ((type = parser.next()) != XmlPullParser.START_TAG &&
5644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    type != XmlPullParser.END_DOCUMENT) {
5654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // Empty loop
5664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
5674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (type != XmlPullParser.START_TAG) {
5684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                throw new XmlPullParserException("No start tag found");
5694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
570e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            return createFromXmlInner(res, parser, attrs, theme);
5714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (XmlPullParserException e) {
5724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
5734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (IOException e) {
5744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
5754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return null;
5774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
579e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    /**
580e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * Create a VectorDrawableCompat from inside an XML document using an optional
581e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * {@link Theme}. Called on a parser positioned at a tag in an XML
582e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * document, tries to create a Drawable from that tag. Returns {@code null}
583e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * if the tag is not a valid drawable.
584e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     */
585af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viverette    @SuppressLint("NewApi")
586e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    public static VectorDrawableCompat createFromXmlInner(Resources r, XmlPullParser parser,
587e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
588e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        final VectorDrawableCompat drawable = new VectorDrawableCompat();
589e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        drawable.inflate(r, parser, attrs, theme);
590e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        return drawable;
591e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    }
592e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
5938fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    static int applyAlpha(int color, float alpha) {
5944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int alphaBytes = Color.alpha(color);
5954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color &= 0x00FFFFFF;
5964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
5974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return color;
5984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
600af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viverette    @SuppressLint("NewApi")
6014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
6024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
6034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
6049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
6059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.inflate(res, parser, attrs);
6069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
6079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflate(res, parser, attrs, null);
6104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
61215375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
6134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
6144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
6159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
616ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.inflate(mDelegateDrawable, res, parser, attrs, theme);
6179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
6189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
6214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
6224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mVPathRenderer = pathRenderer;
6234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
624b6086751979cb14740815502597e9fcfddb7054aztenghui        final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs,
625b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TYPE_ARRAY);
626d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
627d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        updateStateFromTypedArray(a, parser);
6284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        a.recycle();
6294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mChangingConfigurations = getChangingConfigurations();
6304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mCacheDirty = true;
6314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflateInternal(res, parser, attrs, theme);
6324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
6344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
636d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
637d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    /**
638d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
639d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * attribute's enum value.
640d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     */
6416705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu    private static PorterDuff.Mode parseTintModeCompat(int value, Mode defaultMode) {
642d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        switch (value) {
6432c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 3:
6442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_OVER;
6452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 5:
6462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_IN;
6472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 9:
6482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_ATOP;
6492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 14:
6502c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.MULTIPLY;
6512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 15:
6522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SCREEN;
6532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 16:
65472da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                if (Build.VERSION.SDK_INT >= 11) {
65572da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                    return Mode.ADD;
65672da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                } else {
65772da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                    return defaultMode;
65872da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette                }
6592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            default:
6602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return defaultMode;
661d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
662d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    }
663d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
6649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser)
6659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            throws XmlPullParserException {
6669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
6674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
6684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Account for any configuration changes.
6704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
6714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
672d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode",
673b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT_MODE, -1);
6746705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu        state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN);
6754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final ColorStateList tint =
677b6086751979cb14740815502597e9fcfddb7054aztenghui                a.getColorStateList(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT);
6784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint != null) {
6794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
6804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
682d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored",
683b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_AUTO_MIRRORED, state.mAutoMirrored);
684d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
685d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth",
686b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_WIDTH,
6879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportWidth);
6884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
689d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight",
690b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_HEIGHT,
6919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportHeight);
6924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mViewportWidth <= 0) {
6944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportWidth > 0");
6964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
6974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
6984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportHeight > 0");
6994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseWidth = a.getDimension(
702b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_WIDTH, pathRenderer.mBaseWidth);
7034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseHeight = a.getDimension(
704b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_HEIGHT, pathRenderer.mBaseHeight);
7054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mBaseWidth <= 0) {
7064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
7074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires width > 0");
7084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
7094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
7104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires height > 0");
7114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
713d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        // shown up from API 11.
714d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
715b6086751979cb14740815502597e9fcfddb7054aztenghui                AndroidResources.STYLEABLE_VECTOR_DRAWABLE_ALPHA, pathRenderer.getAlpha());
7164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.setAlpha(alphaInFloat);
7174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
718b6086751979cb14740815502597e9fcfddb7054aztenghui        final String name = a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_NAME);
7194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (name != null) {
7204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mRootName = name;
7214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
7224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
7262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                 Theme theme) throws XmlPullParserException, IOException {
7279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
7284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
7294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean noPathTag = true;
7304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Use a stack to help to build the group tree.
7324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // The top of the stack is always the current group.
7334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
7344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        groupStack.push(pathRenderer.mRootGroup);
7354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int eventType = parser.getEventType();
73767b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        final int innerDepth = parser.getDepth() + 1;
73867b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu
73967b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        // Parse everything until the end of the vector element.
74067b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu        while (eventType != XmlPullParser.END_DOCUMENT
74167b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu                && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) {
7424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (eventType == XmlPullParser.START_TAG) {
7434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final VGroup currentGroup = groupStack.peek();
7454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_PATH.equals(tagName)) {
7464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VFullPath path = new VFullPath();
747d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    noPathTag = false;
7534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
7554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VClipPath path = new VClipPath();
756d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
7574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
7584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
7594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
7604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
7624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
7634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup newChildGroup = new VGroup();
764d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    newChildGroup.inflate(res, attrs, theme, parser);
7654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(newChildGroup);
7664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.push(newChildGroup);
7674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newChildGroup.getGroupName() != null) {
7684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
7694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                                newChildGroup);
7704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
7714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
7724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
7744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
7754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_GROUP.equals(tagName)) {
7764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.pop();
7774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            eventType = parser.next();
7804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the tree out for debug.
7834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (DBG_VECTOR_DRAWABLE) {
7844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
7854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (noPathTag) {
7884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final StringBuffer tag = new StringBuffer();
7894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (tag.length() > 0) {
7914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                tag.append(" or ");
7924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
7934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            tag.append(SHAPE_PATH);
7944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException("no " + tag + " defined");
7964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
7974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
7984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
8004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String indent = "";
8014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < level; i++) {
8024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            indent += "    ";
8034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the current node
8054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
8064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                + " rotation is " + currentGroup.mRotate);
8074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
8084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Then print all the children groups
8094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
8104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Object child = currentGroup.mChildren.get(i);
8114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (child instanceof VGroup) {
8124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                printGroupTree((VGroup) child, level + 1);
813d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            } else {
814d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                ((VPath) child).printVPath(level + 1);
8154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    void setAllowCaching(boolean allowCaching) {
8204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mAllowCaching = allowCaching;
8214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
824af6b251c15dab2237fdf100b5ebb9c0851c2d490Alan Viverette    @SuppressLint("NewApi")
8254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean needMirroring() {
8260327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        if (Build.VERSION.SDK_INT < 17) {
8270327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return false;
8280327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        } else {
8290327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu            return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
8300327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu        }
8314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // Extra override functions for delegation for SDK >= 7.
8349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8355f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu    protected void onBoundsChange(Rect bounds) {
8369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8375f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu            mDelegateDrawable.setBounds(bounds);
8389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public int getChangingConfigurations() {
8439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getChangingConfigurations();
8459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
8479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void invalidateSelf() {
8519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.invalidateSelf();
8539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.invalidateSelf();
8569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void scheduleSelf(Runnable what, long when) {
8609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.scheduleSelf(what, when);
8629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.scheduleSelf(what, when);
8659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public boolean setVisible(boolean visible, boolean restart) {
8699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setVisible(visible, restart);
8719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        return super.setVisible(visible, restart);
8739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
8769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void unscheduleSelf(Runnable what) {
8779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
8789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.unscheduleSelf(what);
8799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
8809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.unscheduleSelf(what);
8829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
8839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    /**
885c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu     * Constant state for delegating the creating drawable job for SDK >= 24.
8869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains
8879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * a delegated VectorDrawable instance.
8889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     */
889c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette    @RequiresApi(24)
8909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableDelegateState extends ConstantState {
8919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        private final ConstantState mDelegateState;
8922c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
8939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableDelegateState(ConstantState state) {
8949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateState = state;
8959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
8969f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
8979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
8989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable() {
8999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable();
9019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res) {
9069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(res);
9089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res, Theme theme) {
9139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
9149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable =
9159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    (VectorDrawable) mDelegateState.newDrawable(res, theme);
9169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
9179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public boolean canApplyTheme() {
9219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.canApplyTheme();
9229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
9259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public int getChangingConfigurations() {
9269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.getChangingConfigurations();
9279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
9289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
9299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
9309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableCompatState extends ConstantState {
9314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
9324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        VPathRenderer mVPathRenderer;
9334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mTint = null;
9344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mTintMode = DEFAULT_TINT_MODE;
9354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mAutoMirrored;
9364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Bitmap mCachedBitmap;
9384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int[] mCachedThemeAttrs;
9394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mCachedTint;
9404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mCachedTintMode;
9414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mCachedRootAlpha;
9424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCachedAutoMirrored;
9434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCacheDirty;
9444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        /**
9462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         * Temporary paint object used to draw cached bitmaps.
9472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         */
9484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint mTempPaint;
9494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Deep copy for mutate() or implicitly mutate.
9519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState(VectorDrawableCompatState copy) {
9524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy != null) {
9534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mChangingConfigurations = copy.mChangingConfigurations;
9544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
9554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mFillPaint != null) {
9564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
9574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mStrokePaint != null) {
9594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
9604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
9614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTint = copy.mTint;
9624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTintMode = copy.mTintMode;
9634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mAutoMirrored = copy.mAutoMirrored;
9644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9671f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
9681f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                                                  Rect originalBounds) {
9694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The bitmap's size is the same as the bounds.
9704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Paint p = getPaint(filter);
9711f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
9724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean hasTranslucentRoot() {
9754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mVPathRenderer.getRootAlpha() < 255;
9764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /**
9794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * @return null when there is no need for alpha paint.
9804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
9814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Paint getPaint(ColorFilter filter) {
9824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!hasTranslucentRoot() && filter == null) {
9834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return null;
9844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mTempPaint == null) {
9874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint = new Paint();
9884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint.setFilterBitmap(true);
9894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
9914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setColorFilter(filter);
9924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTempPaint;
9934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void updateCachedBitmap(int width, int height) {
9964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
9974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
9981f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVPathRenderer.draw(tmpCanvas, width, height, null);
9994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10011f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void createCachedBitmapIfNeeded(int width, int height) {
10021f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
10031f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mCachedBitmap = Bitmap.createBitmap(width, height,
10044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        Bitmap.Config.ARGB_8888);
10054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mCacheDirty = true;
10064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseBitmap(int width, int height) {
10114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (width == mCachedBitmap.getWidth()
10124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && height == mCachedBitmap.getHeight()) {
10134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseCache() {
10194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mCacheDirty
10204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTint == mTint
10214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTintMode == mTintMode
10224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedAutoMirrored == mAutoMirrored
10234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
10244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
10254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
10274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void updateCacheStates() {
10304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
10314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // likely hit cache miss more, but practically not much difference.
10324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTint = mTint;
10334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTintMode = mTintMode;
10344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
10354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedAutoMirrored = mAutoMirrored;
10364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCacheDirty = false;
10374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState() {
10404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVPathRenderer = new VPathRenderer();
10414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable() {
10454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable(Resources res) {
10504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
10514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
10544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getChangingConfigurations() {
10554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mChangingConfigurations;
10564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
10584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPathRenderer {
10604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Right now the internal data structure is organized as a tree.
10614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * Each node can be a group node, or a path.
10624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * A group node can have groups or paths as children, but a path node has
10634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * no children.
10644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * One example can be:
10654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                 Root Group
10664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                /    |     \
10674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *           Group    Path    Group
10684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *          /     \             |
10694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *         Path   Path         Path
10704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *
10714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
10724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables that only used temporarily inside the draw() call, so there
10734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // is no need for deep copying.
10744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mPath;
10754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mRenderPath;
10764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
10774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mFinalPathMatrix = new Matrix();
10784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mStrokePaint;
10804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mFillPaint;
10814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private PathMeasure mPathMeasure;
10824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
10844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
10854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int mChangingConfigurations;
10868fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        final VGroup mRootGroup;
10874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseWidth = 0;
10884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseHeight = 0;
10894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportWidth = 0;
10904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportHeight = 0;
10914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mRootAlpha = 0xFF;
10924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mRootName = null;
10934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
10954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer() {
10974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup();
10984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path();
10994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path();
11004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRootAlpha(int alpha) {
11034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = alpha;
11044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getRootAlpha() {
11074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRootAlpha;
11084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
11114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Animator like to use alpha from 0 to 1.
11124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setAlpha(float alpha) {
11134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            setRootAlpha((int) (alpha * 255));
11144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
11174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getAlpha() {
11184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return getRootAlpha() / 255.0f;
11194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer(VPathRenderer copy) {
11224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
11234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path(copy.mPath);
11244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path(copy.mRenderPath);
11254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseWidth = copy.mBaseWidth;
11264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseHeight = copy.mBaseHeight;
11274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportWidth = copy.mViewportWidth;
11284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportHeight = copy.mViewportHeight;
11294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
11304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = copy.mRootAlpha;
11314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootName = copy.mRootName;
11324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy.mRootName != null) {
11334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVGTargetsMap.put(copy.mRootName, this);
11344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
11354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
11382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                   Canvas canvas, int w, int h, ColorFilter filter) {
11394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Calculate current group's matrix by preConcat the parent's and
11404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // and the current one on the top of the stack.
11414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
11424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Mi the local matrix at level i of the group tree.
11434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
11444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
11464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
114704027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            // Save the current clip information, which is local to this group.
114804027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.save();
114904027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
11504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Draw the group tree in the same order as the XML file.
11514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
11524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object child = currentGroup.mChildren.get(i);
11534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (child instanceof VGroup) {
11544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup childGroup = (VGroup) child;
11554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
11564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                            canvas, w, h, filter);
11574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (child instanceof VPath) {
11584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath childPath = (VPath) child;
11594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawPath(currentGroup, childPath, canvas, w, h, filter);
11604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
11614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
116204027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
116304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.restore();
11644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
1167c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas            // Traverse the tree in pre-order to draw.
11684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
11694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
11722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                              ColorFilter filter) {
11734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleX = w / mViewportWidth;
11744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleY = h / mViewportHeight;
11754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float minScale = Math.min(scaleX, scaleY);
11762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
11774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFinalPathMatrix.set(groupStackedMatrix);
11794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
11804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final float matrixScale = getMatrixScale(groupStackedMatrix);
11832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (matrixScale == 0) {
11842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                // When either x or y is scaled to 0, we don't need to draw anything.
11852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return;
11862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
11874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            vPath.toPath(mPath);
11884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Path path = mPath;
11894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath.reset();
11914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (vPath.isClipPath()) {
11934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
119404027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu                canvas.clipPath(mRenderPath);
11954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
11964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                VFullPath fullPath = (VFullPath) vPath;
11974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
11984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
11994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
12004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mPathMeasure == null) {
12024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure = new PathMeasure();
12034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mPathMeasure.setPath(mPath, false);
12054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float len = mPathMeasure.getLength();
12074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    start = start * len;
12084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    end = end * len;
12094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.reset();
12104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (start > end) {
12114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, len, path, true);
12124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(0f, end, path, true);
12134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
12144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, end, path, true);
12154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.rLineTo(0, 0); // fix bug in measure
12174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
12194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
12214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mFillPaint == null) {
12224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint = new Paint();
12234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
12244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setAntiAlias(true);
12254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint fillPaint = mFillPaint;
12284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
12294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColorFilter(filter);
12304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, fillPaint);
12314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
12344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mStrokePaint == null) {
12354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint = new Paint();
12364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
12374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setAntiAlias(true);
12384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint strokePaint = mStrokePaint;
12414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineJoin != null) {
12424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
12434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineCap != null) {
12464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
12474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
12484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
12504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
12514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColorFilter(filter);
12522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    final float finalStrokeScale = minScale * matrixScale;
12532c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
12544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
12554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
12564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private static float cross(float v1x, float v1y, float v2x, float v2y) {
12602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return v1x * v2y - v1y * v2x;
12612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private float getMatrixScale(Matrix groupStackedMatrix) {
12642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Given unit vectors A = (0, 1) and B = (1, 0).
12652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
12662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
12672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
12682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
12692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            //
12702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
12712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // scale on x and y axis, and take the minimal of these two.
12722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For skew case, an unit square will mapped to a parallelogram. And this function will
12732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // return the minimal height of the 2 bases.
12742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float[] unitVectors = new float[]{0, 1, 1, 0};
12752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            groupStackedMatrix.mapVectors(unitVectors);
12762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]);
12772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]);
12782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2],
12792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    unitVectors[3]);
12802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float maxScale = Math.max(scaleX, scaleY);
12812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
12822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float matrixScale = 0;
12832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (maxScale > 0) {
12842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                matrixScale = Math.abs(crossProduct) / maxScale;
12852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (DBG_VECTOR_DRAWABLE) {
12872c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
12882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
12892c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return matrixScale;
12902c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
12914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
12924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VGroup {
12944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
12954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // the parents' local matrices with the current one.
12964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mStackedMatrix = new Matrix();
12974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
12994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
13004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
13014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13028fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        float mRotate = 0;
13034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotX = 0;
13044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotY = 0;
13054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleX = 1;
13064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleY = 1;
13074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateX = 0;
13084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateY = 0;
13094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mLocalMatrix is updated based on the update of transformation information,
13114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // either parsed from the XML or by animation.
13124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mLocalMatrix = new Matrix();
13138fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        int mChangingConfigurations;
13144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
13154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private String mGroupName = null;
13164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
13184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRotate = copy.mRotate;
13194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotX = copy.mPivotX;
13204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotY = copy.mPivotY;
13214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleX = copy.mScaleX;
13224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleY = copy.mScaleY;
13234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateX = copy.mTranslateX;
13244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateY = copy.mTranslateY;
13254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
13264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mGroupName = copy.mGroupName;
13274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
13284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mGroupName != null) {
13294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                targetsMap.put(mGroupName, this);
13304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.set(copy.mLocalMatrix);
13334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final ArrayList<Object> children = copy.mChildren;
13354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < children.size(); i++) {
13364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object copyChild = children.get(i);
13374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copyChild instanceof VGroup) {
13384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup copyGroup = (VGroup) copyChild;
13394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
13404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else {
13414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath newPath = null;
13424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (copyChild instanceof VFullPath) {
13434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VFullPath((VFullPath) copyChild);
13444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else if (copyChild instanceof VClipPath) {
13454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VClipPath((VClipPath) copyChild);
13464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
13474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        throw new IllegalStateException("Unknown object in the tree!");
13484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(newPath);
13504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newPath.mPathName != null) {
13514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        targetsMap.put(newPath.mPathName, newPath);
13524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
13534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
13544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup() {
13584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getGroupName() {
13614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mGroupName;
13624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Matrix getLocalMatrix() {
13654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mLocalMatrix;
13664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1368d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) {
1369b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs,
1370b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP);
1371d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
13724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
13734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1375d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
13764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
13774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
13784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
13804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
13814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1382d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1383d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation",
1384b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_ROTATION, mRotate);
1385d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1386b6086751979cb14740815502597e9fcfddb7054aztenghui            mPivotX = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_X, mPivotX);
1387b6086751979cb14740815502597e9fcfddb7054aztenghui            mPivotY = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_Y, mPivotY);
1388d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1389d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1390d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX",
1391b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_X, mScaleX);
1392d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1393d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1394d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY",
1395b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_Y, mScaleY);
1396d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1397d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX",
1398b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_X, mTranslateX);
1399d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY",
1400b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_Y, mTranslateY);
14014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String groupName =
1403b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_NAME);
14044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (groupName != null) {
14054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mGroupName = groupName;
14064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateLocalMatrix();
14094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateLocalMatrix() {
14124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The order we apply is the same as the
14134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
14144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.reset();
14154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
14164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
14174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
14184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
14194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
14224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getRotation() {
14244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRotate;
14254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRotation(float rotation) {
14294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (rotation != mRotate) {
14304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRotate = rotation;
14314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotX() {
14374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotX;
14384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotX(float pivotX) {
14424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotX != mPivotX) {
14434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotX = pivotX;
14444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotY() {
14504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotY;
14514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotY(float pivotY) {
14554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotY != mPivotY) {
14564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotY = pivotY;
14574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleX() {
14634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleX;
14644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleX(float scaleX) {
14684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleX != mScaleX) {
14694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleX = scaleX;
14704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleY() {
14764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleY;
14774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleY(float scaleY) {
14814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleY != mScaleY) {
14824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleY = scaleY;
14834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateX() {
14894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateX;
14904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateX(float translateX) {
14944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateX != mTranslateX) {
14954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateX = translateX;
14964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
14974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateY() {
15024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateY;
15034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateY(float translateY) {
15074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateY != mTranslateY) {
15084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateY = translateY;
15094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
15104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Common Path information for clip path and normal path.
15164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPath {
15184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        protected PathParser.PathDataNode[] mNodes = null;
15194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mPathName;
15204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
15214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath() {
15234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1526d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void printVPath(int level) {
1527d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String indent = "";
1528d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < level; i++) {
1529d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                indent += "    ";
1530d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1531d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            Log.v(LOGTAG, indent + "current path is :" + mPathName +
1532b6086751979cb14740815502597e9fcfddb7054aztenghui                    " pathData is " + nodesToString(mNodes));
1533d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1534d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1535d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1536b6086751979cb14740815502597e9fcfddb7054aztenghui        public String nodesToString(PathParser.PathDataNode[] nodes) {
1537d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String result = " ";
1538d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < nodes.length; i++) {
1539b6086751979cb14740815502597e9fcfddb7054aztenghui                result += nodes[i].mType + ":";
1540b6086751979cb14740815502597e9fcfddb7054aztenghui                float[] params = nodes[i].mParams;
1541d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                for (int j = 0; j < params.length; j++) {
1542d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    result += params[j] + ",";
1543d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                }
1544d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1545d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            return result;
1546d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1547d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
15484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath(VPath copy) {
15494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPathName = copy.mPathName;
15504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
15514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
15524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void toPath(Path path) {
15554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            path.reset();
15564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mNodes != null) {
15574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
15584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getPathName() {
15624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPathName;
15634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
15664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
15704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
15734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
15744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
15774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public PathParser.PathDataNode[] getPathData() {
15794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mNodes;
15804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
15834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
15844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
15854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // This should not happen in the middle of animation.
15864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.deepCopyNodes(nodes);
15874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
15884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.updateNodes(mNodes, nodes);
15894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
15924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
15944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Clip path, which only has name and pathData.
15954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
15964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VClipPath extends VPath {
15974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath() {
15984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath(VClipPath copy) {
16024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
16034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1605d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
16064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // TODO TINT THEME Not supported yet
1607d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1608d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
1609d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1610d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1611b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs,
1612b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH);
16134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateStateFromTypedArray(a);
16144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
16154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateStateFromTypedArray(TypedArray a) {
16184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
16194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
16204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathName =
1622b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_NAME);
16234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
16244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
16254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
1628b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_PATH_DATA);
16294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
16304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
16314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
16354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
16364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
16374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
16394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
16414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Normal path, which contains all the fill / paint information.
16424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
16434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VFullPath extends VPath {
16444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
16454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
16464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
16474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mStrokeColor = Color.TRANSPARENT;
16494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeWidth = 0;
16504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillColor = Color.TRANSPARENT;
16524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeAlpha = 1.0f;
16534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillRule;
16544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mFillAlpha = 1.0f;
16554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathStart = 0;
16564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathEnd = 1;
16574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathOffset = 0;
16584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
16604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
16614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeMiterlimit = 4;
16624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath() {
16644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
16654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath(VFullPath copy) {
16684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
16694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
16704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = copy.mStrokeColor;
16724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = copy.mStrokeWidth;
16734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = copy.mStrokeAlpha;
16744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = copy.mFillColor;
16754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillRule = copy.mFillRule;
16764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = copy.mFillAlpha;
16774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = copy.mTrimPathStart;
16784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = copy.mTrimPathEnd;
16794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = copy.mTrimPathOffset;
16804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineCap = copy.mStrokeLineCap;
16824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
16834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
16844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
16874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
16884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_BUTT:
16894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.BUTT;
16904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_ROUND:
16914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.ROUND;
16924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_SQUARE:
16934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.SQUARE;
16944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
16954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
16964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
17004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
17014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_MITER:
17024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.MITER;
17034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_ROUND:
17044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.ROUND;
17054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_BEVEL:
17064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.BEVEL;
17074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
17084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
17094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
17144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mThemeAttrs != null;
17154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1717d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
1718b6086751979cb14740815502597e9fcfddb7054aztenghui            final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs,
1719b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH);
1720d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
17214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
17224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1724d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
17254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
17264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
17274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
17294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
17304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // In order to work around the conflicting id issue, we need to double check the
17329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // existence of the attribute.
17339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // B/c if the attribute existed in the compiled XML, then calling TypedArray will be
17349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // safe since the framework will look up in the XML first.
17359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay.
1736d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1737d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
17389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // If there is no pathData in the <path> tag, then this is an empty path,
17399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // nothing need to be drawn.
1740d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1741d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1742d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1743b6086751979cb14740815502597e9fcfddb7054aztenghui            final String pathName = a.getString(
1744b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_NAME);
17454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
17464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
17474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
1749b6086751979cb14740815502597e9fcfddb7054aztenghui                    a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_PATH_DATA);
17504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
17514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
17524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1754d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor",
1755b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_COLOR, mFillColor);
17562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "fillAlpha",
1757b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_ALPHA, mFillAlpha);
1758d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap",
1759b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_CAP, -1);
1760d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap);
1761d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin",
1762b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_JOIN, -1);
1763d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin);
1764d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit",
1765b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_MITER_LIMIT,
17669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    mStrokeMiterlimit);
1767d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor",
1768b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_COLOR, mStrokeColor);
1769d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha",
1770b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_ALPHA, mStrokeAlpha);
1771d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth",
1772b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_WIDTH, mStrokeWidth);
1773d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd",
1774b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_END, mTrimPathEnd);
1775d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset",
1776b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_OFFSET,
1777b6086751979cb14740815502597e9fcfddb7054aztenghui                    mTrimPathOffset);
1778d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart",
1779b6086751979cb14740815502597e9fcfddb7054aztenghui                    AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_START,
1780b6086751979cb14740815502597e9fcfddb7054aztenghui                    mTrimPathStart);
17814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
17844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
17854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mThemeAttrs == null) {
17864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return;
17874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
17884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            /*
17904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * TODO TINT THEME Not supported yet final TypedArray a =
1791d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu             * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath);
17924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * updateStateFromTypedArray(a); a.recycle();
17934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             */
17944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
17974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getStrokeColor() {
17994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeColor;
18004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeColor(int strokeColor) {
18044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = strokeColor;
18054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeWidth() {
18094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeWidth;
18104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeWidth(float strokeWidth) {
18144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = strokeWidth;
18154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeAlpha() {
18194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeAlpha;
18204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeAlpha(float strokeAlpha) {
18244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = strokeAlpha;
18254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getFillColor() {
18294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillColor;
18304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillColor(int fillColor) {
18344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = fillColor;
18354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getFillAlpha() {
18394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillAlpha;
18404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillAlpha(float fillAlpha) {
18444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = fillAlpha;
18454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathStart() {
18494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathStart;
18504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathStart(float trimPathStart) {
18544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = trimPathStart;
18554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathEnd() {
18594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathEnd;
18604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathEnd(float trimPathEnd) {
18644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = trimPathEnd;
18654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathOffset() {
18694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathOffset;
18704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
18724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
18734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathOffset(float trimPathOffset) {
18744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = trimPathOffset;
18754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
18764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
18774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui}
1878