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