14fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/* 24fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Copyright (C) 2015 The Android Open Source Project 34fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 44fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 54fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * in compliance with the License. You may obtain a copy of the License at 64fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 74fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * http://www.apache.org/licenses/LICENSE-2.0 84fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 94fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Unless required by applicable law or agreed to in writing, software distributed under the License 104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * or implied. See the License for the specific language governing permissions and limitations under 124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * the License. 134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuipackage android.support.graphics.drawable; 164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 178e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikasimport static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP; 18e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes 194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.ColorStateList; 204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources; 214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources.Theme; 224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.TypedArray; 234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Bitmap; 244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Canvas; 254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Color; 264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.ColorFilter; 274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Matrix; 284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Paint; 294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Path; 304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PathMeasure; 314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PixelFormat; 324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff; 334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff.Mode; 344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuffColorFilter; 354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Rect; 364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.drawable.Drawable; 379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.graphics.drawable.VectorDrawable; 389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.os.Build; 39968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhuimport android.support.annotation.DrawableRes; 404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.NonNull; 414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.Nullable; 42b6086751979cb14740815502597e9fcfddb7054aztenghuiimport android.support.annotation.RequiresApi; 4367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.annotation.RestrictTo; 4467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.content.res.ResourcesCompat; 45a80878dec1a3689e6e79566a9650de39c3291c01Yuichi Arakiimport android.support.v4.content.res.TypedArrayUtils; 46142a5654b5eff546b6fa1b9b938896356ff9b03bYuichi Arakiimport android.support.v4.graphics.PathParser; 4767b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liuimport android.support.v4.graphics.drawable.DrawableCompat; 484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.v4.util.ArrayMap; 494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.AttributeSet; 500327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhuimport android.util.LayoutDirection; 514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Log; 524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Xml; 534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 54b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParser; 55b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hironoimport org.xmlpull.v1.XmlPullParserException; 56b787498b8054f85d0e1e6a1a107141ec4a49f050Daichi Hirono 574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.io.IOException; 584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.ArrayList; 594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.Stack; 604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/** 62c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}. 63ab9d2bf6fe28ff4a95985526daa128239c03d821Teng-Hui Zhu * For older API version, this class lets you create a drawable based on an XML vector graphic. 6495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/> 657c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API. 667c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * In order to refer to VectorDrawableCompat inside a XML file, you can use app:srcCompat attribute 677c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * in AppCompat library's ImageButton or ImageView. 6895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/> 6995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <strong>Note:</strong> To optimize for the re-drawing performance, one bitmap cache is created 7095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * for each VectorDrawableCompat. Therefore, referring to the same VectorDrawableCompat means 7195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * sharing the same bitmap cache. If these references don't agree upon on the same size, the bitmap 7295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * will be recreated and redrawn every time size is changed. In other words, if a VectorDrawable is 7395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * used for different sizes, it is more efficient to create multiple VectorDrawables, one for each 7495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * size. 7595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/> 7695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * VectorDrawableCompat can be defined in an XML file with the <code><vector></code> element. 7795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/> 7895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The VectorDrawableCompat has the following elements: 7995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <p/> 8095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code><vector></code></dt> 8195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 8295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define a vector drawable 8395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 8495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt> 8595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of this vector drawable.</dd> 8695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:width</code></dt> 8795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic width of the drawable. 8895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd> 8995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:height</code></dt> 9095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the intrinsic height the drawable. 9195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * This support all the dimension units, normally specified with dp.</dd> 9295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportWidth</code></dt> 9395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the width of the viewport space. Viewport is basically 9495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd> 9595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:viewportHeight</code></dt> 9695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Used to define the height of the viewport space. Viewport is basically 9795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the virtual canvas where the paths are drawn on.</dd> 9895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tint</code></dt> 9995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd> 10095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:tintMode</code></dt> 101791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The Porter-Duff blending mode for the tint color. Default is src_in.</dd> 10295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:autoMirrored</code></dt> 10395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Indicates if the drawable needs to be mirrored when its layout direction is 104791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * RTL (right-to-left). Default is false.</dd> 10595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:alpha</code></dt> 106791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of this drawable. Default is 1.</dd> 10795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd> 10895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl> 10995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * 11095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 11195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code><group></code></dt> 11295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines a group of paths or subgroups, plus transformation information. 11395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * The transformations are defined in the same coordinates as the viewport. 11495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * And the transformations are applied in the order of scale, rotate then translate. 11595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 11695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt> 11795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the group.</dd> 11895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:rotation</code></dt> 119791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The degrees of rotation of the group. Default is 0.</dd> 12095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotX</code></dt> 12195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The X coordinate of the pivot for the scale and rotation of the group. 122791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd> 12395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pivotY</code></dt> 12495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The Y coordinate of the pivot for the scale and rotation of the group. 125791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd> 12695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleX</code></dt> 127791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the X Coordinate. Default is 1.</dd> 12895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:scaleY</code></dt> 129791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The amount of scale on the Y coordinate. Default is 1.</dd> 13095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateX</code></dt> 13195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the X coordinate. 132791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd> 13395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:translateY</code></dt> 13495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>The amount of translation on the Y coordinate. 135791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * This is defined in the viewport space. Default is 0.</dd> 13695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd> 13795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl> 13895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * 13995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 14095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code><path></code></dt> 14195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines paths to be drawn. 14295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 14395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt> 14495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the path.</dd> 14595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt> 14695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path data using exactly same format as "d" attribute 14795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data. This is defined in the viewport space.</dd> 14895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillColor</code></dt> 14995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to fill the path. 15095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value. 15195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path fill is drawn if this property is not specified.</dd> 15295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeColor</code></dt> 15395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Specifies the color used to draw the path outline. 15495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * If this property is animated, any value set by the animation will override the original value. 15595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * No path outline is drawn if this property is not specified.</dd> 15695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeWidth</code></dt> 157791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The width a path stroke. Default is 0.</dd> 15895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeAlpha</code></dt> 159791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity of a path stroke. Default is 1.</dd> 16095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:fillAlpha</code></dt> 161791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The opacity to fill the path with. Default is 1.</dd> 16295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathStart</code></dt> 163791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the start, in the range from 0 to 1. Default is 0.</dd> 16495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathEnd</code></dt> 165791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>The fraction of the path to trim from the end, in the range from 0 to 1. Default is 1.</dd> 16695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:trimPathOffset</code></dt> 16795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Shift trim region (allows showed region to include the start and end), in the range 168791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * from 0 to 1. Default is 0.</dd> 16995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineCap</code></dt> 170791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the linecap for a stroked path: butt, round, square. Default is butt.</dd> 17195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeLineJoin</code></dt> 172791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the lineJoin for a stroked path: miter,round,bevel. Default is miter.</dd> 17395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:strokeMiterLimit</code></dt> 174791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <dd>Sets the Miter limit for a stroked path. Default is 4.</dd> 17595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd> 17695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl> 17795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * 17895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 17995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code><clip-path></code></dt> 18095276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines path to be the current clip. Note that the clip path only apply to 18195276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * the current group and its children. 18295276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dl> 18395276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:name</code></dt> 18495276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines the name of the clip path.</dd> 18595276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dt><code>android:pathData</code></dt> 18695276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * <dd>Defines clip path using the same format as "d" attribute 18795276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * in the SVG's path data.</dd> 18895276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl></dd> 18995276d3d3d07337500b6255d6a6ae031591784f3Teng-Hui Zhu * </dl> 190791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <p/> 191791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * Note that theme attributes in XML file are supported through 192791d564c66cf6bfc38413a35bf767b41cf019887Teng-Hui Zhu * <code>{@link #inflate(Resources, XmlPullParser, AttributeSet, Theme)}</code>. 1934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 194968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhupublic class VectorDrawableCompat extends VectorDrawableCommon { 1954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui static final String LOGTAG = "VectorDrawableCompat"; 1964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN; 1984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final String SHAPE_CLIP_PATH = "clip-path"; 2004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final String SHAPE_GROUP = "group"; 2014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final String SHAPE_PATH = "path"; 2024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final String SHAPE_VECTOR = "vector"; 2034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINECAP_BUTT = 0; 2054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINECAP_ROUND = 1; 2064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINECAP_SQUARE = 2; 2074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINEJOIN_MITER = 0; 2094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINEJOIN_ROUND = 1; 2104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final int LINEJOIN_BEVEL = 2; 2114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // Cap the bitmap size, such that it won't hurt the performance too much 2131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // and it won't crash due to a very large scale. 2141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // The drawable will look blurry above this size. 2151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu private static final int MAX_CACHED_BITMAP_SIZE = 2048; 2161f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 217d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu private static final boolean DBG_VECTOR_DRAWABLE = false; 2184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private VectorDrawableCompatState mVectorState; 2204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private PorterDuffColorFilter mTintFilter; 2224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private ColorFilter mColorFilter; 2234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private boolean mMutated; 2254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise, 2274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // caching the bitmap by default is allowed. 2284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private boolean mAllowCaching = true; 2294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // The Constant state associated with the <code>mDelegateDrawable</code>. 2319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private ConstantState mCachedConstantStateDelegate; 2329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 2331f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // Temp variable, only for saving "new" operation at the draw() time. 2341f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu private final float[] mTmpFloats = new float[9]; 2351f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu private final Matrix mTmpMatrix = new Matrix(); 2361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu private final Rect mTmpBounds = new Rect(); 2371f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 2388fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas VectorDrawableCompat() { 2399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mVectorState = new VectorDrawableCompatState(); 2404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2428fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas VectorDrawableCompat(@NonNull VectorDrawableCompatState state) { 2434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVectorState = state; 2444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 2454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 2484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public Drawable mutate() { 2499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 2509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.mutate(); 2519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return this; 2529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 2539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 2544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!mMutated && super.mutate() == this) { 2559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mVectorState = new VectorDrawableCompatState(mVectorState); 2564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mMutated = true; 2574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return this; 2594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Object getTargetByName(String name) { 2624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mVectorState.mVPathRenderer.mVGTargetsMap.get(name); 2634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 2664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public ConstantState getConstantState() { 267c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette if (mDelegateDrawable != null && Build.VERSION.SDK_INT >= 24) { 2682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Such that the configuration can be refreshed. 2692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return new VectorDrawableDelegateState(mDelegateDrawable.getConstantState()); 2709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 2714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVectorState.mChangingConfigurations = getChangingConfigurations(); 2724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mVectorState; 2734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 2744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 2754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 2764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void draw(Canvas canvas) { 2779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 2789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.draw(canvas); 2799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 2809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 2811f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // We will offset the bounds for drawBitmap, so copyBounds() here instead 2821f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // of getBounds(). 2831f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu copyBounds(mTmpBounds); 2841f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) { 2851f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // Nothing to draw 2861f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu return; 2871f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu } 2889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 2891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // Color filters always override tint filters. 2901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter); 2911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 2921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // The imageView can scale the canvas in different ways, in order to 2931f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // avoid blurry scaling, we have to draw into a bitmap with exact pixel 2941f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // size first. This bitmap size is determined by the bounds and the 2951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // canvas scale. 2961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvas.getMatrix(mTmpMatrix); 2971f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mTmpMatrix.getValues(mTmpFloats); 2981f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]); 2991f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]); 3001f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 3011f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu float canvasSkewX = Math.abs(mTmpFloats[Matrix.MSKEW_X]); 3021f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu float canvasSkewY = Math.abs(mTmpFloats[Matrix.MSKEW_Y]); 3031f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 3041f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // When there is any rotation / skew, then the scale value is not valid. 3051f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu if (canvasSkewX != 0 || canvasSkewY != 0) { 3061f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvasScaleX = 1.0f; 3071f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvasScaleY = 1.0f; 3081f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu } 3091f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 3101f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX); 3111f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY); 3121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth); 3131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight); 3141f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu 3151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu if (scaledWidth <= 0 || scaledHeight <= 0) { 3164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return; 3174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final int saveCount = canvas.save(); 3201f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvas.translate(mTmpBounds.left, mTmpBounds.top); 3214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3221f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // Handle RTL mirroring. 3231f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu final boolean needMirroring = needMirroring(); 3244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (needMirroring) { 3251f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvas.translate(mTmpBounds.width(), 0); 3264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui canvas.scale(-1.0f, 1.0f); 3274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3291f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // At this point, canvas has been translated to the right position. 3301f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // And we use this bound for the destination rect for the drawBitmap, so 3311f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu // we offset to (0, 0); 3321f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mTmpBounds.offsetTo(0, 0); 3334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3341f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight); 3354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!mAllowCaching) { 3361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mVectorState.updateCachedBitmap(scaledWidth, scaledHeight); 3374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 3384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!mVectorState.canReuseCache()) { 3391f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mVectorState.updateCachedBitmap(scaledWidth, scaledHeight); 3404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVectorState.updateCacheStates(); 3414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3431f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds); 3444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui canvas.restoreToCount(saveCount); 3454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 34715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 3484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getAlpha() { 3499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 350ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu return DrawableCompat.getAlpha(mDelegateDrawable); 3519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 3529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 3534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mVectorState.mVPathRenderer.getRootAlpha(); 3544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 3574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setAlpha(int alpha) { 3589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 3599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.setAlpha(alpha); 3609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 3619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 3629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 3634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) { 3644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVectorState.mVPathRenderer.setRootAlpha(alpha); 3654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui invalidateSelf(); 3664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 3704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setColorFilter(ColorFilter colorFilter) { 3719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 3729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.setColorFilter(colorFilter); 3739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 3749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 3759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 3764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mColorFilter = colorFilter; 3774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui invalidateSelf(); 3784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 3804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 3814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Ensures the tint filter is consistent with the current tint color and 3824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * mode. 3834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 3844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint, 3852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu PorterDuff.Mode tintMode) { 3864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (tint == null || tintMode == null) { 3874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return null; 3884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7. 3904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Therefore we create a new one all the time here. Don't expect this is called often. 3914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final int color = tint.getColorForState(getState(), Color.TRANSPARENT); 3924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return new PorterDuffColorFilter(color, tintMode); 3934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 3944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 39515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 3964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setTint(int tint) { 3979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 398ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu DrawableCompat.setTint(mDelegateDrawable, tint); 3999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 4009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui setTintList(ColorStateList.valueOf(tint)); 4034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 40515375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 4064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setTintList(ColorStateList tint) { 4079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 408ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu DrawableCompat.setTintList(mDelegateDrawable, tint); 4099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 4109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 4134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (state.mTint != tint) { 4144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mTint = tint; 4154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); 4164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui invalidateSelf(); 4174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 42015375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 4214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setTintMode(Mode tintMode) { 4229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 423ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu DrawableCompat.setTintMode(mDelegateDrawable, tintMode); 4249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 4259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 4284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (state.mTintMode != tintMode) { 4294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mTintMode = tintMode; 4304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); 4314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui invalidateSelf(); 4324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 4364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean isStateful() { 4379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 4389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.isStateful(); 4399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return super.isStateful() || (mVectorState != null && mVectorState.mTint != null 4424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && mVectorState.mTint.isStateful()); 4434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 4464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui protected boolean onStateChange(int[] stateSet) { 4479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 4489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.setState(stateSet); 4499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 4524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (state.mTint != null && state.mTintMode != null) { 4539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 4544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui invalidateSelf(); 4554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return true; 4564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 4584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 4614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getOpacity() { 4629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 4639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.getOpacity(); 4649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return PixelFormat.TRANSLUCENT; 4674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 4704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getIntrinsicWidth() { 4719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 4729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.getIntrinsicWidth(); 4739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return (int) mVectorState.mVPathRenderer.mBaseWidth; 4764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 4794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getIntrinsicHeight() { 4809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 4819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.getIntrinsicHeight(); 4829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return (int) mVectorState.mVPathRenderer.mBaseHeight; 4854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Don't support re-applying themes. The initial theme loading is working. 48815375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 4894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean canApplyTheme() { 4909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 491ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu DrawableCompat.canApplyTheme(mDelegateDrawable); 4929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 4939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 4944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 4954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 4964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 4970327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu @Override 4980327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu public boolean isAutoMirrored() { 4990327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu if (mDelegateDrawable != null) { 5000327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu return DrawableCompat.isAutoMirrored(mDelegateDrawable); 5010327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu } 5020327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu return mVectorState.mAutoMirrored; 5030327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu } 5040327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu 5050327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu @Override 5060327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu public void setAutoMirrored(boolean mirrored) { 5070327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu if (mDelegateDrawable != null) { 5080327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu DrawableCompat.setAutoMirrored(mDelegateDrawable, mirrored); 5090327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu return; 5100327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu } 5110327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu mVectorState.mAutoMirrored = mirrored; 5120327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu } 5134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 5144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This 5154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * is used to calculate the path animation accuracy. 5164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 5174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * @hide 5184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 5198e10080c914d1ad0784394fa3026b85535535847Aurimas Liutikas @RestrictTo(LIBRARY_GROUP) 5204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getPixelSize() { 521791777822ec5bd177f5c03655411486e150be6edztenghui if (mVectorState == null || mVectorState.mVPathRenderer == null 52298ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas || mVectorState.mVPathRenderer.mBaseWidth == 0 52398ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas || mVectorState.mVPathRenderer.mBaseHeight == 0 52498ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas || mVectorState.mVPathRenderer.mViewportHeight == 0 52598ec0d5b378c8417156037af6389e90f0074a26eAurimas Liutikas || mVectorState.mVPathRenderer.mViewportWidth == 0) { 5264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return 1; // fall back to 1:1 pixel mapping. 5274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth; 5294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight; 5304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth; 5314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight; 5324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float scaleX = viewportWidth / intrinsicWidth; 5334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float scaleY = viewportHeight / intrinsicHeight; 5344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Math.min(scaleX, scaleY); 5354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 5374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 5384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Create a VectorDrawableCompat object. 5394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 5402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * @param res the resources. 5414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * @param resId the resource ID for VectorDrawableCompat object. 5424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * @param theme the theme of this vector drawable, it can be null. 5434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * @return a new VectorDrawableCompat or null if parsing error is found. 5444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 5454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Nullable 5464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId, 5472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu @Nullable Theme theme) { 548c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu if (Build.VERSION.SDK_INT >= 24) { 5499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompat drawable = new VectorDrawableCompat(); 550ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu drawable.mDelegateDrawable = ResourcesCompat.getDrawable(res, resId, theme); 5512c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu drawable.mCachedConstantStateDelegate = new VectorDrawableDelegateState( 5522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu drawable.mDelegateDrawable.getConstantState()); 5539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return drawable; 5549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 5559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 5564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui try { 5574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final XmlPullParser parser = res.getXml(resId); 5584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final AttributeSet attrs = Xml.asAttributeSet(parser); 5594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int type; 5604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui while ((type = parser.next()) != XmlPullParser.START_TAG && 5614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui type != XmlPullParser.END_DOCUMENT) { 5624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Empty loop 5634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (type != XmlPullParser.START_TAG) { 5654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException("No start tag found"); 5664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 567e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes return createFromXmlInner(res, parser, attrs, theme); 5684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } catch (XmlPullParserException e) { 5694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Log.e(LOGTAG, "parser error", e); 5704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } catch (IOException e) { 5714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Log.e(LOGTAG, "parser error", e); 5724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return null; 5744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 576e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes /** 577e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes * Create a VectorDrawableCompat from inside an XML document using an optional 578e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes * {@link Theme}. Called on a parser positioned at a tag in an XML 579e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes * document, tries to create a Drawable from that tag. Returns {@code null} 580e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes * if the tag is not a valid drawable. 581e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes */ 582e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes public static VectorDrawableCompat createFromXmlInner(Resources r, XmlPullParser parser, 583e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException { 584e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes final VectorDrawableCompat drawable = new VectorDrawableCompat(); 585e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes drawable.inflate(r, parser, attrs, theme); 586e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes return drawable; 587e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes } 588e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes 5898fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas static int applyAlpha(int color, float alpha) { 5904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int alphaBytes = Color.alpha(color); 5914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui color &= 0x00FFFFFF; 5924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui color |= ((int) (alphaBytes * alpha)) << 24; 5934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return color; 5944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 5954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 5964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 5974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs) 5984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throws XmlPullParserException, IOException { 5999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 6009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.inflate(res, parser, attrs); 6019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 6029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 6039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 6044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui inflate(res, parser, attrs, null); 6054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 6064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 60715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas @Override 6084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme) 6094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throws XmlPullParserException, IOException { 6109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 611ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu DrawableCompat.inflate(mDelegateDrawable, res, parser, attrs, theme); 6129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 6139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 6149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 6159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 6164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VPathRenderer pathRenderer = new VPathRenderer(); 6174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mVPathRenderer = pathRenderer; 6184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 619b6086751979cb14740815502597e9fcfddb7054aztenghui final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs, 620b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TYPE_ARRAY); 621d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 622d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu updateStateFromTypedArray(a, parser); 6234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui a.recycle(); 6244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mChangingConfigurations = getChangingConfigurations(); 6254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mCacheDirty = true; 6264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui inflateInternal(res, parser, attrs, theme); 6274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 6284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 6294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 6304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 631d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 632d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu /** 633d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode 634d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu * attribute's enum value. 635d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu */ 6366705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu private static PorterDuff.Mode parseTintModeCompat(int value, Mode defaultMode) { 637d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu switch (value) { 6382c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 3: 6392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return Mode.SRC_OVER; 6402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 5: 6412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return Mode.SRC_IN; 6422c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 9: 6432c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return Mode.SRC_ATOP; 6442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 14: 6452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return Mode.MULTIPLY; 6462c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 15: 6472c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return Mode.SCREEN; 6482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu case 16: 64972da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette if (Build.VERSION.SDK_INT >= 11) { 65072da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette return Mode.ADD; 65172da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette } else { 65272da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette return defaultMode; 65372da1bc528fab5a641cd464af4e0f56749f912c6Alan Viverette } 6542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu default: 6552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return defaultMode; 656d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 657d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 658d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 6599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) 6609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu throws XmlPullParserException { 6619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 6624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VPathRenderer pathRenderer = state.mVPathRenderer; 6634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 6644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Account for any configuration changes. 6654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // state.mChangingConfigurations |= Utils.getChangingConfigurations(a); 6664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 667d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode", 668b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT_MODE, -1); 6696705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN); 6704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 6719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final ColorStateList tint = 672b6086751979cb14740815502597e9fcfddb7054aztenghui a.getColorStateList(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_TINT); 6734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (tint != null) { 6744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mTint = tint; 6754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 6764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 677d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored", 678b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_AUTO_MIRRORED, state.mAutoMirrored); 679d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 680d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth", 681b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_WIDTH, 6829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu pathRenderer.mViewportWidth); 6834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 684d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight", 685b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_VIEWPORT_HEIGHT, 6869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu pathRenderer.mViewportHeight); 6874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 6884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathRenderer.mViewportWidth <= 0) { 6894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException(a.getPositionDescription() + 6904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui "<vector> tag requires viewportWidth > 0"); 6914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (pathRenderer.mViewportHeight <= 0) { 6924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException(a.getPositionDescription() + 6934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui "<vector> tag requires viewportHeight > 0"); 6944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 6954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 6964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mBaseWidth = a.getDimension( 697b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_WIDTH, pathRenderer.mBaseWidth); 6984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mBaseHeight = a.getDimension( 699b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_HEIGHT, pathRenderer.mBaseHeight); 7004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathRenderer.mBaseWidth <= 0) { 7014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException(a.getPositionDescription() + 7024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui "<vector> tag requires width > 0"); 7034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (pathRenderer.mBaseHeight <= 0) { 7044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException(a.getPositionDescription() + 7054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui "<vector> tag requires height > 0"); 7064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 708d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu // shown up from API 11. 709d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha", 710b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_ALPHA, pathRenderer.getAlpha()); 7114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.setAlpha(alphaInFloat); 7124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 713b6086751979cb14740815502597e9fcfddb7054aztenghui final String name = a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_NAME); 7144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (name != null) { 7154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mRootName = name; 7164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mVGTargetsMap.put(name, pathRenderer); 7174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs, 7212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Theme theme) throws XmlPullParserException, IOException { 7229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final VectorDrawableCompatState state = mVectorState; 7234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VPathRenderer pathRenderer = state.mVPathRenderer; 7244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui boolean noPathTag = true; 7254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Use a stack to help to build the group tree. 7274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // The top of the stack is always the current group. 7284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final Stack<VGroup> groupStack = new Stack<VGroup>(); 7294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui groupStack.push(pathRenderer.mRootGroup); 7304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int eventType = parser.getEventType(); 73267b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu final int innerDepth = parser.getDepth() + 1; 73367b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu 73467b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu // Parse everything until the end of the vector element. 73567b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu while (eventType != XmlPullParser.END_DOCUMENT 73667b6c5f8b82d730f3d39287af5e98adbd77c6ebfDoris Liu && (parser.getDepth() >= innerDepth || eventType != XmlPullParser.END_TAG)) { 7374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (eventType == XmlPullParser.START_TAG) { 7384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final String tagName = parser.getName(); 7394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VGroup currentGroup = groupStack.peek(); 7404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (SHAPE_PATH.equals(tagName)) { 7414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VFullPath path = new VFullPath(); 742d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu path.inflate(res, attrs, theme, parser); 7434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui currentGroup.mChildren.add(path); 7444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (path.getPathName() != null) { 7454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 7464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui noPathTag = false; 7484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mChangingConfigurations |= path.mChangingConfigurations; 7494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (SHAPE_CLIP_PATH.equals(tagName)) { 7504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final VClipPath path = new VClipPath(); 751d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu path.inflate(res, attrs, theme, parser); 7524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui currentGroup.mChildren.add(path); 7534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (path.getPathName() != null) { 7544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 7554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mChangingConfigurations |= path.mChangingConfigurations; 7574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (SHAPE_GROUP.equals(tagName)) { 7584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VGroup newChildGroup = new VGroup(); 759d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu newChildGroup.inflate(res, attrs, theme, parser); 7604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui currentGroup.mChildren.add(newChildGroup); 7614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui groupStack.push(newChildGroup); 7624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (newChildGroup.getGroupName() != null) { 7634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(), 7644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui newChildGroup); 7654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui state.mChangingConfigurations |= newChildGroup.mChangingConfigurations; 7674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (eventType == XmlPullParser.END_TAG) { 7694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final String tagName = parser.getName(); 7704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (SHAPE_GROUP.equals(tagName)) { 7714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui groupStack.pop(); 7724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui eventType = parser.next(); 7754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Print the tree out for debug. 7784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (DBG_VECTOR_DRAWABLE) { 7794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui printGroupTree(pathRenderer.mRootGroup, 0); 7804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (noPathTag) { 7834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final StringBuffer tag = new StringBuffer(); 7844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (tag.length() > 0) { 7864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui tag.append(" or "); 7874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui tag.append(SHAPE_PATH); 7894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new XmlPullParserException("no " + tag + " defined"); 7914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 7944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void printGroupTree(VGroup currentGroup, int level) { 7954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui String indent = ""; 7964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui for (int i = 0; i < level; i++) { 7974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui indent += " "; 7984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 7994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Print the current node 8004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName() 8014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui + " rotation is " + currentGroup.mRotate); 8024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString()); 8034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Then print all the children groups 8044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui for (int i = 0; i < currentGroup.mChildren.size(); i++) { 8054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Object child = currentGroup.mChildren.get(i); 8064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (child instanceof VGroup) { 8074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui printGroupTree((VGroup) child, level + 1); 808d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } else { 809d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu ((VPath) child).printVPath(level + 1); 8104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 8114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 8124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 8134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 8144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setAllowCaching(boolean allowCaching) { 8154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mAllowCaching = allowCaching; 8164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 8174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 8184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+. 8194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private boolean needMirroring() { 820905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette if (Build.VERSION.SDK_INT >= 17) { 8210327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; 822905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette } else { 823905bcd294a7351749c60382eab03aa0c679e08bbAlan Viverette return false; 8240327a65adda49ea1f39440a3127836b41ff43084Teng-Hui Zhu } 8254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 8264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 8279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // Extra override functions for delegation for SDK >= 7. 8289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8295f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu protected void onBoundsChange(Rect bounds) { 8309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8315f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu mDelegateDrawable.setBounds(bounds); 8329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public int getChangingConfigurations() { 8379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.getChangingConfigurations(); 8399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return super.getChangingConfigurations() | mVectorState.getChangingConfigurations(); 8419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public void invalidateSelf() { 8459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8469f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.invalidateSelf(); 8479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 8489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu super.invalidateSelf(); 8509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public void scheduleSelf(Runnable what, long when) { 8549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.scheduleSelf(what, when); 8569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 8579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu super.scheduleSelf(what, when); 8599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public boolean setVisible(boolean visible, boolean restart) { 8639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateDrawable.setVisible(visible, restart); 8659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return super.setVisible(visible, restart); 8679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public void unscheduleSelf(Runnable what) { 8719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu if (mDelegateDrawable != null) { 8729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateDrawable.unscheduleSelf(what); 8739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return; 8749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu super.unscheduleSelf(what); 8769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu /** 879c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * Constant state for delegating the creating drawable job for SDK >= 24. 8809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains 8819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu * a delegated VectorDrawable instance. 8829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu */ 883c69882cb9b130902c1554ef5d3e3b06d776cd796Alan Viverette @RequiresApi(24) 8849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private static class VectorDrawableDelegateState extends ConstantState { 8859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private final ConstantState mDelegateState; 8862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 8879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public VectorDrawableDelegateState(ConstantState state) { 8889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mDelegateState = state; 8899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public Drawable newDrawable() { 8939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu VectorDrawableCompat drawableCompat = new VectorDrawableCompat(); 8949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(); 8959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return drawableCompat; 8969f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 8979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 8989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 8999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public Drawable newDrawable(Resources res) { 9009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu VectorDrawableCompat drawableCompat = new VectorDrawableCompat(); 9019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(res); 9029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return drawableCompat; 9039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 9049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 9059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 9069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public Drawable newDrawable(Resources res, Theme theme) { 9079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu VectorDrawableCompat drawableCompat = new VectorDrawableCompat(); 9089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu drawableCompat.mDelegateDrawable = 9099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu (VectorDrawable) mDelegateState.newDrawable(res, theme); 9109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return drawableCompat; 9119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 9129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 9139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 9149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public boolean canApplyTheme() { 9159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateState.canApplyTheme(); 9169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 9179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 9189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu @Override 9199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public int getChangingConfigurations() { 9209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu return mDelegateState.getChangingConfigurations(); 9219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 9229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu } 9239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu 9249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu private static class VectorDrawableCompatState extends ConstantState { 9254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mChangingConfigurations; 9264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VPathRenderer mVPathRenderer; 9274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui ColorStateList mTint = null; 9284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Mode mTintMode = DEFAULT_TINT_MODE; 9294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui boolean mAutoMirrored; 9304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Bitmap mCachedBitmap; 9324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int[] mCachedThemeAttrs; 9334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui ColorStateList mCachedTint; 9344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Mode mCachedTintMode; 9354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mCachedRootAlpha; 9364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui boolean mCachedAutoMirrored; 9374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui boolean mCacheDirty; 9384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9392c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu /** 9402c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu * Temporary paint object used to draw cached bitmaps. 9412c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu */ 9424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Paint mTempPaint; 9434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Deep copy for mutate() or implicitly mutate. 9459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public VectorDrawableCompatState(VectorDrawableCompatState copy) { 9464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copy != null) { 9474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChangingConfigurations = copy.mChangingConfigurations; 9484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVPathRenderer = new VPathRenderer(copy.mVPathRenderer); 9494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copy.mVPathRenderer.mFillPaint != null) { 9504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint); 9514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copy.mVPathRenderer.mStrokePaint != null) { 9534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint); 9544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTint = copy.mTint; 9564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTintMode = copy.mTintMode; 9574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mAutoMirrored = copy.mAutoMirrored; 9584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9611f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter, 9621f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu Rect originalBounds) { 9634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // The bitmap's size is the same as the bounds. 9644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final Paint p = getPaint(filter); 9651f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu canvas.drawBitmap(mCachedBitmap, null, originalBounds, p); 9664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean hasTranslucentRoot() { 9694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mVPathRenderer.getRootAlpha() < 255; 9704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 9734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * @return null when there is no need for alpha paint. 9744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 9754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public Paint getPaint(ColorFilter filter) { 9764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!hasTranslucentRoot() && filter == null) { 9774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return null; 9784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mTempPaint == null) { 9814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTempPaint = new Paint(); 9824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTempPaint.setFilterBitmap(true); 9834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTempPaint.setAlpha(mVPathRenderer.getRootAlpha()); 9854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTempPaint.setColorFilter(filter); 9864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTempPaint; 9874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu public void updateCachedBitmap(int width, int height) { 9904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCachedBitmap.eraseColor(Color.TRANSPARENT); 9914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Canvas tmpCanvas = new Canvas(mCachedBitmap); 9921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mVPathRenderer.draw(tmpCanvas, width, height, null); 9934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 9944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 9951f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu public void createCachedBitmapIfNeeded(int width, int height) { 9961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu if (mCachedBitmap == null || !canReuseBitmap(width, height)) { 9971f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu mCachedBitmap = Bitmap.createBitmap(width, height, 9984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Bitmap.Config.ARGB_8888); 9994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCacheDirty = true; 10004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean canReuseBitmap(int width, int height) { 10054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (width == mCachedBitmap.getWidth() 10064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && height == mCachedBitmap.getHeight()) { 10074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return true; 10084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 10104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean canReuseCache() { 10134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!mCacheDirty 10144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && mCachedTint == mTint 10154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && mCachedTintMode == mTintMode 10164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && mCachedAutoMirrored == mAutoMirrored 10174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { 10184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return true; 10194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 10214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void updateCacheStates() { 10244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Use shallow copy here and shallow comparison in canReuseCache(), 10254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // likely hit cache miss more, but practically not much difference. 10264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCachedTint = mTint; 10274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCachedTintMode = mTintMode; 10284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCachedRootAlpha = mVPathRenderer.getRootAlpha(); 10294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCachedAutoMirrored = mAutoMirrored; 10304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mCacheDirty = false; 10314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10339f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu public VectorDrawableCompatState() { 10344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVPathRenderer = new VPathRenderer(); 10354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 10384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public Drawable newDrawable() { 10394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return new VectorDrawableCompat(this); 10404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 10434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public Drawable newDrawable(Resources res) { 10444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return new VectorDrawableCompat(this); 10454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 10484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getChangingConfigurations() { 10494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mChangingConfigurations; 10504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static class VPathRenderer { 10544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /* Right now the internal data structure is organized as a tree. 10554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Each node can be a group node, or a path. 10564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * A group node can have groups or paths as children, but a path node has 10574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * no children. 10584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * One example can be: 10594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Root Group 10604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * / | \ 10614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Group Path Group 10624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * / \ | 10634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Path Path Path 10644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * 10654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 10664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Variables that only used temporarily inside the draw() call, so there 10674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // is no need for deep copying. 10684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private final Path mPath; 10694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private final Path mRenderPath; 10704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static final Matrix IDENTITY_MATRIX = new Matrix(); 10714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private final Matrix mFinalPathMatrix = new Matrix(); 10724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private Paint mStrokePaint; 10744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private Paint mFillPaint; 10754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private PathMeasure mPathMeasure; 10764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui ///////////////////////////////////////////////////// 10784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 10794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private int mChangingConfigurations; 10808fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas final VGroup mRootGroup; 10814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mBaseWidth = 0; 10824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mBaseHeight = 0; 10834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mViewportWidth = 0; 10844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mViewportHeight = 0; 10854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mRootAlpha = 0xFF; 10864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui String mRootName = null; 10874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>(); 10894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VPathRenderer() { 10914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRootGroup = new VGroup(); 10924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPath = new Path(); 10934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRenderPath = new Path(); 10944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 10964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setRootAlpha(int alpha) { 10974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRootAlpha = alpha; 10984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 10994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public int getRootAlpha() { 11014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mRootAlpha; 11024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // setAlpha() and getAlpha() are used mostly for animation purpose, since 11054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Animator like to use alpha from 0 to 1. 11064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setAlpha(float alpha) { 11074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui setRootAlpha((int) (alpha * 255)); 11084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 11114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getAlpha() { 11124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return getRootAlpha() / 255.0f; 11134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VPathRenderer(VPathRenderer copy) { 11164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); 11174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPath = new Path(copy.mPath); 11184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRenderPath = new Path(copy.mRenderPath); 11194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mBaseWidth = copy.mBaseWidth; 11204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mBaseHeight = copy.mBaseHeight; 11214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mViewportWidth = copy.mViewportWidth; 11224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mViewportHeight = copy.mViewportHeight; 11234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChangingConfigurations = copy.mChangingConfigurations; 11244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRootAlpha = copy.mRootAlpha; 11254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRootName = copy.mRootName; 11264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copy.mRootName != null) { 11274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mVGTargetsMap.put(copy.mRootName, this); 11284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix, 11322c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Canvas canvas, int w, int h, ColorFilter filter) { 11334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Calculate current group's matrix by preConcat the parent's and 11344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // and the current one on the top of the stack. 11354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Basically the Mfinal = Mviewport * M0 * M1 * M2; 11364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Mi the local matrix at level i of the group tree. 11374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui currentGroup.mStackedMatrix.set(currentMatrix); 11384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix); 11404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 114104027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu // Save the current clip information, which is local to this group. 114204027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu canvas.save(); 114304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu 11444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Draw the group tree in the same order as the XML file. 11454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui for (int i = 0; i < currentGroup.mChildren.size(); i++) { 11464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Object child = currentGroup.mChildren.get(i); 11474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (child instanceof VGroup) { 11484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VGroup childGroup = (VGroup) child; 11494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui drawGroupTree(childGroup, currentGroup.mStackedMatrix, 11504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui canvas, w, h, filter); 11514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (child instanceof VPath) { 11524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VPath childPath = (VPath) child; 11534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui drawPath(currentGroup, childPath, canvas, w, h, filter); 11544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 115604027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu 115704027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu canvas.restore(); 11584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void draw(Canvas canvas, int w, int h, ColorFilter filter) { 1161c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas // Traverse the tree in pre-order to draw. 11624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter); 11634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h, 11662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu ColorFilter filter) { 11674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final float scaleX = w / mViewportWidth; 11684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final float scaleY = h / mViewportHeight; 11694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final float minScale = Math.min(scaleX, scaleY); 11702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final Matrix groupStackedMatrix = vGroup.mStackedMatrix; 11714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mFinalPathMatrix.set(groupStackedMatrix); 11734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFinalPathMatrix.postScale(scaleX, scaleY); 11744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 11762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final float matrixScale = getMatrixScale(groupStackedMatrix); 11772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (matrixScale == 0) { 11782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // When either x or y is scaled to 0, we don't need to draw anything. 11792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return; 11802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 11814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui vPath.toPath(mPath); 11824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final Path path = mPath; 11834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRenderPath.reset(); 11854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (vPath.isClipPath()) { 11874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRenderPath.addPath(path, mFinalPathMatrix); 118804027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu canvas.clipPath(mRenderPath); 11894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 11904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VFullPath fullPath = (VFullPath) vPath; 11914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) { 11924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f; 11934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f; 11944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 11954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mPathMeasure == null) { 11964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathMeasure = new PathMeasure(); 11974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 11984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathMeasure.setPath(mPath, false); 11994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float len = mPathMeasure.getLength(); 12014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui start = start * len; 12024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui end = end * len; 12034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui path.reset(); 12044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (start > end) { 12054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathMeasure.getSegment(start, len, path, true); 12064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathMeasure.getSegment(0f, end, path, true); 12074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 12084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathMeasure.getSegment(start, end, path, true); 12094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui path.rLineTo(0, 0); // fix bug in measure 12114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRenderPath.addPath(path, mFinalPathMatrix); 12134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (fullPath.mFillColor != Color.TRANSPARENT) { 12154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mFillPaint == null) { 12164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillPaint = new Paint(); 12174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillPaint.setStyle(Paint.Style.FILL); 12184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillPaint.setAntiAlias(true); 12194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final Paint fillPaint = mFillPaint; 12224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha)); 12234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui fillPaint.setColorFilter(filter); 1224401033a37f69a78f27f748c3ef95e7291e1339ffztenghui mRenderPath.setFillType(fullPath.mFillRule == 0 ? Path.FillType.WINDING 1225401033a37f69a78f27f748c3ef95e7291e1339ffztenghui : Path.FillType.EVEN_ODD); 12264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui canvas.drawPath(mRenderPath, fillPaint); 12274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (fullPath.mStrokeColor != Color.TRANSPARENT) { 12304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mStrokePaint == null) { 12314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokePaint = new Paint(); 12324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokePaint.setStyle(Paint.Style.STROKE); 12334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokePaint.setAntiAlias(true); 12344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final Paint strokePaint = mStrokePaint; 12374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (fullPath.mStrokeLineJoin != null) { 12384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin); 12394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (fullPath.mStrokeLineCap != null) { 12424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui strokePaint.setStrokeCap(fullPath.mStrokeLineCap); 12434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit); 12464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha)); 12474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui strokePaint.setColorFilter(filter); 12482c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu final float finalStrokeScale = minScale * matrixScale; 12492c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale); 12504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui canvas.drawPath(mRenderPath, strokePaint); 12514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12542c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 12552c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private static float cross(float v1x, float v1y, float v2x, float v2y) { 12562c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return v1x * v2y - v1y * v2x; 12572c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 12582c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 12592c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu private float getMatrixScale(Matrix groupStackedMatrix) { 12602c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Given unit vectors A = (0, 1) and B = (1, 0). 12612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'. 12622c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)), 12632c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|); 12642c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0. 12652c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // 12662c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // For non-skew case, which is most of the cases, matrix scale is computing exactly the 12672c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // scale on x and y axis, and take the minimal of these two. 12682c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // For skew case, an unit square will mapped to a parallelogram. And this function will 12692c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu // return the minimal height of the 2 bases. 12702c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float[] unitVectors = new float[]{0, 1, 1, 0}; 12712c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu groupStackedMatrix.mapVectors(unitVectors); 12722c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]); 12732c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]); 12742c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2], 12752c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu unitVectors[3]); 12762c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float maxScale = Math.max(scaleX, scaleY); 12772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu 12782c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu float matrixScale = 0; 12792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (maxScale > 0) { 12802c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu matrixScale = Math.abs(crossProduct) / maxScale; 12812c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 12822c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu if (DBG_VECTOR_DRAWABLE) { 12832c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale); 12842c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 12852c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu return matrixScale; 12862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu } 12874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 12884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static class VGroup { 12904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // mStackedMatrix is only used temporarily when drawing, it combines all 12914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // the parents' local matrices with the current one. 12924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private final Matrix mStackedMatrix = new Matrix(); 12934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui ///////////////////////////////////////////////////// 12954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 12964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final ArrayList<Object> mChildren = new ArrayList<Object>(); 12974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 12988fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas float mRotate = 0; 12994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mPivotX = 0; 13004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mPivotY = 0; 13014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mScaleX = 1; 13024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mScaleY = 1; 13034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mTranslateX = 0; 13044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private float mTranslateY = 0; 13054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // mLocalMatrix is updated based on the update of transformation information, 13074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // either parsed from the XML or by animation. 13084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private final Matrix mLocalMatrix = new Matrix(); 13098fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas int mChangingConfigurations; 13104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private int[] mThemeAttrs; 13114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private String mGroupName = null; 13124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) { 13144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRotate = copy.mRotate; 13154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPivotX = copy.mPivotX; 13164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPivotY = copy.mPivotY; 13174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mScaleX = copy.mScaleX; 13184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mScaleY = copy.mScaleY; 13194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTranslateX = copy.mTranslateX; 13204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTranslateY = copy.mTranslateY; 13214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mThemeAttrs = copy.mThemeAttrs; 13224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mGroupName = copy.mGroupName; 13234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChangingConfigurations = copy.mChangingConfigurations; 13244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mGroupName != null) { 13254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui targetsMap.put(mGroupName, this); 13264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.set(copy.mLocalMatrix); 13294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui final ArrayList<Object> children = copy.mChildren; 13314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui for (int i = 0; i < children.size(); i++) { 13324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Object copyChild = children.get(i); 13334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copyChild instanceof VGroup) { 13344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VGroup copyGroup = (VGroup) copyChild; 13354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChildren.add(new VGroup(copyGroup, targetsMap)); 13364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 13374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui VPath newPath = null; 13384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (copyChild instanceof VFullPath) { 13394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui newPath = new VFullPath((VFullPath) copyChild); 13404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else if (copyChild instanceof VClipPath) { 13414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui newPath = new VClipPath((VClipPath) copyChild); 13424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 13434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui throw new IllegalStateException("Unknown object in the tree!"); 13444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChildren.add(newPath); 13464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (newPath.mPathName != null) { 13474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui targetsMap.put(newPath.mPathName, newPath); 13484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VGroup() { 13544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public String getGroupName() { 13574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mGroupName; 13584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public Matrix getLocalMatrix() { 13614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mLocalMatrix; 13624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1364d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) { 1365b6086751979cb14740815502597e9fcfddb7054aztenghui final TypedArray a = TypedArrayUtils.obtainAttributes(res, theme, attrs, 1366b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP); 1367d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu updateStateFromTypedArray(a, parser); 13684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui a.recycle(); 13694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 13704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1371d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) { 13724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Account for any configuration changes. 13734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // mChangingConfigurations |= Utils.getChangingConfigurations(a); 13744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Extract the theme attributes, if any. 13764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs(); 13774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1378d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu // This is added in API 11 1379d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation", 1380b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_ROTATION, mRotate); 1381d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1382b6086751979cb14740815502597e9fcfddb7054aztenghui mPivotX = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_X, mPivotX); 1383b6086751979cb14740815502597e9fcfddb7054aztenghui mPivotY = a.getFloat(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_PIVOT_Y, mPivotY); 1384d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1385d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu // This is added in API 11 1386d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX", 1387b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_X, mScaleX); 1388d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1389d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu // This is added in API 11 1390d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY", 1391b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_SCALE_Y, mScaleY); 1392d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1393d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX", 1394b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_X, mTranslateX); 1395d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY", 1396b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_TRANSLATE_Y, mTranslateY); 13974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 13989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final String groupName = 1399b6086751979cb14740815502597e9fcfddb7054aztenghui a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_GROUP_NAME); 14004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (groupName != null) { 14014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mGroupName = groupName; 14024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void updateLocalMatrix() { 14084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // The order we apply is the same as the 14094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // RenderNode.cpp::applyViewPropertyTransforms(). 14104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.reset(); 14114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.postTranslate(-mPivotX, -mPivotY); 14124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.postScale(mScaleX, mScaleY); 14134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.postRotate(mRotate, 0, 0); 14144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); 14154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 14184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getRotation() { 14204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mRotate; 14214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setRotation(float rotation) { 14254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (rotation != mRotate) { 14264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mRotate = rotation; 14274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getPivotX() { 14334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mPivotX; 14344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setPivotX(float pivotX) { 14384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pivotX != mPivotX) { 14394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPivotX = pivotX; 14404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getPivotY() { 14464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mPivotY; 14474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setPivotY(float pivotY) { 14514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pivotY != mPivotY) { 14524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPivotY = pivotY; 14534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getScaleX() { 14594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mScaleX; 14604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setScaleX(float scaleX) { 14644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (scaleX != mScaleX) { 14654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mScaleX = scaleX; 14664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getScaleY() { 14724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mScaleY; 14734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setScaleY(float scaleY) { 14774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (scaleY != mScaleY) { 14784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mScaleY = scaleY; 14794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getTranslateX() { 14854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTranslateX; 14864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setTranslateX(float translateX) { 14904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (translateX != mTranslateX) { 14914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTranslateX = translateX; 14924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 14934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 14954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 14964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 14974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public float getTranslateY() { 14984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTranslateY; 14994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 15024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setTranslateY(float translateY) { 15034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (translateY != mTranslateY) { 15044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTranslateY = translateY; 15054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateLocalMatrix(); 15064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 15114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Common Path information for clip path and normal path. 15124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 15134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static class VPath { 15144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui protected PathParser.PathDataNode[] mNodes = null; 15154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui String mPathName; 15164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mChangingConfigurations; 15174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VPath() { 15194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Empty constructor. 15204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1522d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu public void printVPath(int level) { 1523d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu String indent = ""; 1524d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu for (int i = 0; i < level; i++) { 1525d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu indent += " "; 1526d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1527d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu Log.v(LOGTAG, indent + "current path is :" + mPathName + 1528b6086751979cb14740815502597e9fcfddb7054aztenghui " pathData is " + nodesToString(mNodes)); 1529d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1530d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1531d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1532b6086751979cb14740815502597e9fcfddb7054aztenghui public String nodesToString(PathParser.PathDataNode[] nodes) { 1533d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu String result = " "; 1534d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu for (int i = 0; i < nodes.length; i++) { 1535b6086751979cb14740815502597e9fcfddb7054aztenghui result += nodes[i].mType + ":"; 1536b6086751979cb14740815502597e9fcfddb7054aztenghui float[] params = nodes[i].mParams; 1537d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu for (int j = 0; j < params.length; j++) { 1538d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu result += params[j] + ","; 1539d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1540d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1541d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu return result; 1542d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1543d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 15444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VPath(VPath copy) { 15454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathName = copy.mPathName; 15464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mChangingConfigurations = copy.mChangingConfigurations; 15474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mNodes = PathParser.deepCopyNodes(copy.mNodes); 15484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void toPath(Path path) { 15514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui path.reset(); 15524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mNodes != null) { 15534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui PathParser.PathDataNode.nodesToPath(mNodes, path); 15544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public String getPathName() { 15584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mPathName; 15594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean canApplyTheme() { 15624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 15634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void applyTheme(Theme t) { 15664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean isClipPath() { 15694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return false; 15704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 15734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 15744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public PathParser.PathDataNode[] getPathData() { 15754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mNodes; 15764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 15794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void setPathData(PathParser.PathDataNode[] nodes) { 15804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (!PathParser.canMorph(mNodes, nodes)) { 15814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // This should not happen in the middle of animation. 15824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mNodes = PathParser.deepCopyNodes(nodes); 15834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } else { 15844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui PathParser.updateNodes(mNodes, nodes); 15854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 15904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Clip path, which only has name and pathData. 15914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 15924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static class VClipPath extends VPath { 15934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VClipPath() { 15944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Empty constructor. 15954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 15964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 15974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VClipPath(VClipPath copy) { 15984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui super(copy); 15994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1601d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) { 16024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // TODO TINT THEME Not supported yet 1603d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData"); 1604d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu if (!hasPathData) { 1605d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu return; 1606d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1607b6086751979cb14740815502597e9fcfddb7054aztenghui final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs, 1608b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH); 16094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui updateStateFromTypedArray(a); 16104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui a.recycle(); 16114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private void updateStateFromTypedArray(TypedArray a) { 16144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Account for any configuration changes. 16154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // mChangingConfigurations |= Utils.getChangingConfigurations(a);; 16164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final String pathName = 1618b6086751979cb14740815502597e9fcfddb7054aztenghui a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_NAME); 16194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathName != null) { 16204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathName = pathName; 16214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final String pathData = 1624b6086751979cb14740815502597e9fcfddb7054aztenghui a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_CLIP_PATH_PATH_DATA); 16254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathData != null) { 16264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mNodes = PathParser.createNodesFromPathData(pathData); 16274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 16314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean isClipPath() { 16324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return true; 16334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /** 16374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Normal path, which contains all the fill / paint information. 16384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 16394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private static class VFullPath extends VPath { 16404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui ///////////////////////////////////////////////////// 16414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 16424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private int[] mThemeAttrs; 16434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mStrokeColor = Color.TRANSPARENT; 16454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mStrokeWidth = 0; 16464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int mFillColor = Color.TRANSPARENT; 16484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mStrokeAlpha = 1.0f; 1649401033a37f69a78f27f748c3ef95e7291e1339ffztenghui int mFillRule = 0; // 0 is default value as "non-zero" fill type. 16504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mFillAlpha = 1.0f; 16514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mTrimPathStart = 0; 16524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mTrimPathEnd = 1; 16534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mTrimPathOffset = 0; 16544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Paint.Cap mStrokeLineCap = Paint.Cap.BUTT; 16564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui Paint.Join mStrokeLineJoin = Paint.Join.MITER; 16574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float mStrokeMiterlimit = 4; 16584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VFullPath() { 16604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Empty constructor. 16614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public VFullPath(VFullPath copy) { 16644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui super(copy); 16654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mThemeAttrs = copy.mThemeAttrs; 16664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeColor = copy.mStrokeColor; 16684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeWidth = copy.mStrokeWidth; 16694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeAlpha = copy.mStrokeAlpha; 16704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillColor = copy.mFillColor; 16714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillRule = copy.mFillRule; 16724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillAlpha = copy.mFillAlpha; 16734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathStart = copy.mTrimPathStart; 16744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathEnd = copy.mTrimPathEnd; 16754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathOffset = copy.mTrimPathOffset; 16764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeLineCap = copy.mStrokeLineCap; 16784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeLineJoin = copy.mStrokeLineJoin; 16794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeMiterlimit = copy.mStrokeMiterlimit; 16804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) { 16834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui switch (id) { 16844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINECAP_BUTT: 16854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Cap.BUTT; 16864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINECAP_ROUND: 16874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Cap.ROUND; 16884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINECAP_SQUARE: 16894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Cap.SQUARE; 16904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui default: 16914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return defValue; 16924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 16944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 16954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) { 16964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui switch (id) { 16974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINEJOIN_MITER: 16984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Join.MITER; 16994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINEJOIN_ROUND: 17004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Join.ROUND; 17014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui case LINEJOIN_BEVEL: 17024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return Paint.Join.BEVEL; 17034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui default: 17044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return defValue; 17054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 17094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public boolean canApplyTheme() { 17104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mThemeAttrs != null; 17114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1713d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) { 1714b6086751979cb14740815502597e9fcfddb7054aztenghui final TypedArray a = TypedArrayUtils.obtainAttributes(r, theme, attrs, 1715b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH); 1716d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu updateStateFromTypedArray(a, parser); 17174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui a.recycle(); 17184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1720d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) { 17214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Account for any configuration changes. 17224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // mChangingConfigurations |= Utils.getChangingConfigurations(a); 17234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui // Extract the theme attributes, if any. 17254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs(); 17264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // In order to work around the conflicting id issue, we need to double check the 17289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // existence of the attribute. 17299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // B/c if the attribute existed in the compiled XML, then calling TypedArray will be 17309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // safe since the framework will look up in the XML first. 17319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay. 1732d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData"); 1733d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu if (!hasPathData) { 17349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // If there is no pathData in the <path> tag, then this is an empty path, 17359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu // nothing need to be drawn. 1736d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu return; 1737d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu } 1738d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu 1739b6086751979cb14740815502597e9fcfddb7054aztenghui final String pathName = a.getString( 1740b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_NAME); 17414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathName != null) { 17424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mPathName = pathName; 17434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu final String pathData = 1745b6086751979cb14740815502597e9fcfddb7054aztenghui a.getString(AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_PATH_DATA); 17464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (pathData != null) { 17474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mNodes = PathParser.createNodesFromPathData(pathData); 17484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 1750d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor", 1751b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_COLOR, mFillColor); 17522c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "fillAlpha", 1753b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_FILL_ALPHA, mFillAlpha); 1754d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap", 1755b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_CAP, -1); 1756d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap); 1757d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin", 1758b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_LINE_JOIN, -1); 1759d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin); 1760d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit", 1761b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_MITER_LIMIT, 17629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu mStrokeMiterlimit); 1763d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor", 1764b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_COLOR, mStrokeColor); 1765d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha", 1766b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_ALPHA, mStrokeAlpha); 1767d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth", 1768b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_STROKE_WIDTH, mStrokeWidth); 1769d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd", 1770b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_END, mTrimPathEnd); 1771d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset", 1772b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_OFFSET, 1773b6086751979cb14740815502597e9fcfddb7054aztenghui mTrimPathOffset); 1774d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart", 1775b6086751979cb14740815502597e9fcfddb7054aztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_START, 1776b6086751979cb14740815502597e9fcfddb7054aztenghui mTrimPathStart); 1777401033a37f69a78f27f748c3ef95e7291e1339ffztenghui mFillRule = TypedArrayUtils.getNamedInt(a, parser, "fillType", 1778401033a37f69a78f27f748c3ef95e7291e1339ffztenghui AndroidResources.STYLEABLE_VECTOR_DRAWABLE_PATH_TRIM_PATH_FILLTYPE, 1779401033a37f69a78f27f748c3ef95e7291e1339ffztenghui mFillRule); 17804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @Override 17834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui public void applyTheme(Theme t) { 17844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui if (mThemeAttrs == null) { 17854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return; 17864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /* 17894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * TODO TINT THEME Not supported yet final TypedArray a = 1790d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath); 17914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * updateStateFromTypedArray(a); a.recycle(); 17924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */ 17934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 17944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 17954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 17964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 17974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int getStrokeColor() { 17984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mStrokeColor; 17994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setStrokeColor(int strokeColor) { 18034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeColor = strokeColor; 18044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getStrokeWidth() { 18084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mStrokeWidth; 18094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setStrokeWidth(float strokeWidth) { 18134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeWidth = strokeWidth; 18144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getStrokeAlpha() { 18184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mStrokeAlpha; 18194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setStrokeAlpha(float strokeAlpha) { 18234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mStrokeAlpha = strokeAlpha; 18244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui int getFillColor() { 18284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mFillColor; 18294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setFillColor(int fillColor) { 18334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillColor = fillColor; 18344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getFillAlpha() { 18384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mFillAlpha; 18394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setFillAlpha(float fillAlpha) { 18434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mFillAlpha = fillAlpha; 18444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getTrimPathStart() { 18484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTrimPathStart; 18494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setTrimPathStart(float trimPathStart) { 18534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathStart = trimPathStart; 18544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getTrimPathEnd() { 18584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTrimPathEnd; 18594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setTrimPathEnd(float trimPathEnd) { 18634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathEnd = trimPathEnd; 18644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui float getTrimPathOffset() { 18684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui return mTrimPathOffset; 18694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui 18714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui @SuppressWarnings("unused") 18724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui void setTrimPathOffset(float trimPathOffset) { 18734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui mTrimPathOffset = trimPathOffset; 18744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui } 18764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui} 1877