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