VectorDrawable.java revision 35289f12d6cb0f0db67489876c805ad4a3cbd5f6
1abb7d134c02ac60091108c491dafb00877093170John Hoford/* 2abb7d134c02ac60091108c491dafb00877093170John Hoford * Copyright (C) 2014 The Android Open Source Project 3abb7d134c02ac60091108c491dafb00877093170John Hoford * 4abb7d134c02ac60091108c491dafb00877093170John Hoford * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5abb7d134c02ac60091108c491dafb00877093170John Hoford * in compliance with the License. You may obtain a copy of the License at 6abb7d134c02ac60091108c491dafb00877093170John Hoford * 7abb7d134c02ac60091108c491dafb00877093170John Hoford * http://www.apache.org/licenses/LICENSE-2.0 8abb7d134c02ac60091108c491dafb00877093170John Hoford * 9abb7d134c02ac60091108c491dafb00877093170John Hoford * Unless required by applicable law or agreed to in writing, software distributed under the License 10abb7d134c02ac60091108c491dafb00877093170John Hoford * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11abb7d134c02ac60091108c491dafb00877093170John Hoford * or implied. See the License for the specific language governing permissions and limitations under 12abb7d134c02ac60091108c491dafb00877093170John Hoford * the License. 13abb7d134c02ac60091108c491dafb00877093170John Hoford */ 14abb7d134c02ac60091108c491dafb00877093170John Hoford 15abb7d134c02ac60091108c491dafb00877093170John Hofordpackage android.graphics.drawable; 16abb7d134c02ac60091108c491dafb00877093170John Hoford 1717cd4dfe3a05c2eddbcbc76066ff3b13fc3f2c8bAlan Viveretteimport android.annotation.NonNull; 1895080637db69ffa4f31f18f32878ddd2457e6857ztenghuiimport android.annotation.Nullable; 19b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList; 20abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources; 21abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources.Theme; 224b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viveretteimport android.content.res.TypedArray; 23482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghuiimport android.graphics.Bitmap; 24abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Canvas; 252af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghuiimport android.graphics.Color; 26abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.ColorFilter; 2787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viveretteimport android.graphics.Insets; 28abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Matrix; 29abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Paint; 30abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Path; 31abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PathMeasure; 32abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PixelFormat; 33b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuffColorFilter; 34abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Rect; 35b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode; 36e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.ArrayMap; 37abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.AttributeSet; 3895080637db69ffa4f31f18f32878ddd2457e6857ztenghuiimport android.util.DisplayMetrics; 39738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghuiimport android.util.LayoutDirection; 40abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.Log; 419af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghuiimport android.util.MathUtils; 42cf4832f69c8786b098ce18c24319021f8cd6733aztenghuiimport android.util.PathParser; 434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport android.util.Xml; 44abb7d134c02ac60091108c491dafb00877093170John Hoford 45abb7d134c02ac60091108c491dafb00877093170John Hofordimport com.android.internal.R; 46abb7d134c02ac60091108c491dafb00877093170John Hoford 47abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParser; 48abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParserException; 49abb7d134c02ac60091108c491dafb00877093170John Hoford 50abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.io.IOException; 51abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.util.ArrayList; 524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghuiimport java.util.Stack; 534b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette 54abb7d134c02ac60091108c491dafb00877093170John Hoford/** 556beeb75723cec42603b47664bce794a2b97d7bacChet Haase * This lets you create a drawable based on an XML vector graphic. It can be 56d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * defined in an XML file with the <code><vector></code> element. 57abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/> 5846e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * The vector drawable has the following elements: 59abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/> 60177dffd869ff1f5bdf816faead01a7dc4980bf75ztenghui * <dt><code><vector></code></dt> 61a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 620ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define a vector drawable 63a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 64c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt> 65c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of this vector drawable.</dd> 66a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:width</code></dt> 670ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the intrinsic width of the drawable. 68a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd> 69a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:height</code></dt> 700ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the intrinsic height the drawable. 71a95c8abb366d9c39450513335f550b56da13b30aztenghui * This support all the dimension units, normally specified with dp.</dd> 72a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportWidth</code></dt> 730ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the width of the viewport space. Viewport is basically 74a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd> 75a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:viewportHeight</code></dt> 760ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Used to define the height of the viewport space. Viewport is basically 77a95c8abb366d9c39450513335f550b56da13b30aztenghui * the virtual canvas where the paths are drawn on.</dd> 78a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tint</code></dt> 79a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd> 80a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:tintMode</code></dt> 81a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd> 82a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:autoMirrored</code></dt> 83a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Indicates if the drawable needs to be mirrored when its layout direction is 84a95c8abb366d9c39450513335f550b56da13b30aztenghui * RTL (right-to-left).</dd> 85c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:alpha</code></dt> 86c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>The opacity of this drawable.</dd> 87a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd> 88a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl> 89a95c8abb366d9c39450513335f550b56da13b30aztenghui * 90a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 916d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dt><code><group></code></dt> 92452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>Defines a group of paths or subgroups, plus transformation information. 93452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * The transformations are defined in the same coordinates as the viewport. 94a95c8abb366d9c39450513335f550b56da13b30aztenghui * And the transformations are applied in the order of scale, rotate then translate. 95a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 96c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dt><code>android:name</code></dt> 97c3fdffa98136bdad1fee9c77598d541d792920e1ztenghui * <dd>Defines the name of the group.</dd> 98a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:rotation</code></dt> 99a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The degrees of rotation of the group.</dd> 100a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pivotX</code></dt> 101a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The X coordinate of the pivot for the scale and rotation of the group. 102a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd> 103a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pivotY</code></dt> 104a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The Y coordinate of the pivot for the scale and rotation of the group. 105a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd> 106a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleX</code></dt> 107a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the X Coordinate.</dd> 108a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:scaleY</code></dt> 109a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of scale on the Y coordinate.</dd> 110a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateX</code></dt> 111a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the X coordinate. 112a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd> 113a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:translateY</code></dt> 114a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The amount of translation on the Y coordinate. 115a95c8abb366d9c39450513335f550b56da13b30aztenghui * This is defined in the viewport space.</dd> 116a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd> 117a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl> 118a95c8abb366d9c39450513335f550b56da13b30aztenghui * 119a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 120abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code><path></code></dt> 1216d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dd>Defines paths to be drawn. 122abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl> 123a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt> 124a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the path.</dd> 125a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt> 1260ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Defines path data using exactly same format as "d" attribute 127a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data. This is defined in the viewport space.</dd> 128a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:fillColor</code></dt> 129a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui * <dd>Defines the color to fill the path (none if not present).</dd> 130a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeColor</code></dt> 131d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Defines the color to draw the path outline (none if not present).</dd> 132a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeWidth</code></dt> 133a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The width a path stroke.</dd> 1342e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:strokeAlpha</code></dt> 1352e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity of a path stroke.</dd> 1362e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dt><code>android:fillAlpha</code></dt> 1372e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui * <dd>The opacity to fill the path with.</dd> 138a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathStart</code></dt> 139a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd> 140a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathEnd</code></dt> 141a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd> 142a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:trimPathOffset</code></dt> 143a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Shift trim region (allows showed region to include the start and end), in the range 144a95c8abb366d9c39450513335f550b56da13b30aztenghui * from 0 to 1.</dd> 145a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineCap</code></dt> 146a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the linecap for a stroked path: butt, round, square.</dd> 147a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeLineJoin</code></dt> 148a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd> 149a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:strokeMiterLimit</code></dt> 150a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Sets the Miter limit for a stroked path.</dd> 151a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd> 152a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl> 153a95c8abb366d9c39450513335f550b56da13b30aztenghui * 154a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 155a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code><clip-path></code></dt> 1566fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * <dd>Defines path to be the current clip. Note that the clip path only apply to 1576fbcefe4d7248912cd797de376eb25c5ace1544dztenghui * the current group and its children. 158a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dl> 159a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:name</code></dt> 160a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dd>Defines the name of the clip path.</dd> 161a95c8abb366d9c39450513335f550b56da13b30aztenghui * <dt><code>android:pathData</code></dt> 1620ea3aca4eb5c920fa43dab1ea027c322d23b9bdaztenghui * <dd>Defines clip path using the same format as "d" attribute 163a95c8abb366d9c39450513335f550b56da13b30aztenghui * in the SVG's path data.</dd> 164a95c8abb366d9c39450513335f550b56da13b30aztenghui * </dl></dd> 165abb7d134c02ac60091108c491dafb00877093170John Hoford * </dl> 166a95c8abb366d9c39450513335f550b56da13b30aztenghui * <li>Here is a simple VectorDrawable in this vectordrawable.xml file. 167a95c8abb366d9c39450513335f550b56da13b30aztenghui * <pre> 168a95c8abb366d9c39450513335f550b56da13b30aztenghui * <vector xmlns:android="http://schemas.android.com/apk/res/android" 169a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:height="64dp" 170a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:width="64dp" 171a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:viewportHeight="600" 172a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:viewportWidth="600" > 173a95c8abb366d9c39450513335f550b56da13b30aztenghui * <group 174a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:name="rotationGroup" 175a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:pivotX="300.0" 176a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:pivotY="300.0" 177a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:rotation="45.0" > 178a95c8abb366d9c39450513335f550b56da13b30aztenghui * <path 179a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:name="v" 180a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:fillColor="#000000" 181a95c8abb366d9c39450513335f550b56da13b30aztenghui * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> 182a95c8abb366d9c39450513335f550b56da13b30aztenghui * </group> 183a95c8abb366d9c39450513335f550b56da13b30aztenghui * </vector> 184a95c8abb366d9c39450513335f550b56da13b30aztenghui * </pre></li> 185abb7d134c02ac60091108c491dafb00877093170John Hoford */ 186a95c8abb366d9c39450513335f550b56da13b30aztenghui 187abb7d134c02ac60091108c491dafb00877093170John Hofordpublic class VectorDrawable extends Drawable { 1889453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette private static final String LOGTAG = VectorDrawable.class.getSimpleName(); 1899453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 190a95c8abb366d9c39450513335f550b56da13b30aztenghui private static final String SHAPE_CLIP_PATH = "clip-path"; 1916d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui private static final String SHAPE_GROUP = "group"; 192abb7d134c02ac60091108c491dafb00877093170John Hoford private static final String SHAPE_PATH = "path"; 193abb7d134c02ac60091108c491dafb00877093170John Hoford private static final String SHAPE_VECTOR = "vector"; 194abb7d134c02ac60091108c491dafb00877093170John Hoford 195abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINECAP_BUTT = 0; 196abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINECAP_ROUND = 1; 197abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINECAP_SQUARE = 2; 1989453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 199abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINEJOIN_MITER = 0; 200abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINEJOIN_ROUND = 1; 201abb7d134c02ac60091108c491dafb00877093170John Hoford private static final int LINEJOIN_BEVEL = 2; 2029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 20335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // Cap the bitmap size, such that it won't hurt the performance too much 20435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // and it won't crash due to a very large scale. 20535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // The drawable will look blurry above this size. 20635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui private static final int MAX_CACHED_BITMAP_SIZE = 2048; 20735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui 2084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private static final boolean DBG_VECTOR_DRAWABLE = false; 2094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 21055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private VectorDrawableState mVectorState; 211e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 212b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette private PorterDuffColorFilter mTintFilter; 213b07b086bd42181f62718a6394b56be3917b12511Alan Viverette private ColorFilter mColorFilter; 214b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 21555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private boolean mMutated; 21655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 217482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise, 218482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui // caching the bitmap by default is allowed. 219482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui private boolean mAllowCaching = true; 220482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui 22195080637db69ffa4f31f18f32878ddd2457e6857ztenghui // Given the virtual display setup, the dpi can be different than the inflation's dpi. 22295080637db69ffa4f31f18f32878ddd2457e6857ztenghui // Therefore, we need to scale the values we got from the getDimension*(). 22395080637db69ffa4f31f18f32878ddd2457e6857ztenghui private int mDpiScaledWidth = 0; 22495080637db69ffa4f31f18f32878ddd2457e6857ztenghui private int mDpiScaledHeight = 0; 22595080637db69ffa4f31f18f32878ddd2457e6857ztenghui private Insets mDpiScaleInsets = Insets.NONE; 22695080637db69ffa4f31f18f32878ddd2457e6857ztenghui 22735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // Temp variable, only for saving "new" operation at the draw() time. 22835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui private final float[] mTmpFloats = new float[9]; 22935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui private final Matrix mTmpMatrix = new Matrix(); 23035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui private final Rect mTmpBounds = new Rect(); 23135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui 232abb7d134c02ac60091108c491dafb00877093170John Hoford public VectorDrawable() { 23395080637db69ffa4f31f18f32878ddd2457e6857ztenghui this(null, null); 234abb7d134c02ac60091108c491dafb00877093170John Hoford } 235abb7d134c02ac60091108c491dafb00877093170John Hoford 23695080637db69ffa4f31f18f32878ddd2457e6857ztenghui private VectorDrawable(@NonNull VectorDrawableState state, @Nullable Resources res) { 23795080637db69ffa4f31f18f32878ddd2457e6857ztenghui if (state == null) { 23895080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState = new VectorDrawableState(); 23995080637db69ffa4f31f18f32878ddd2457e6857ztenghui } else { 24095080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState = state; 24195080637db69ffa4f31f18f32878ddd2457e6857ztenghui mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 24295080637db69ffa4f31f18f32878ddd2457e6857ztenghui } 24395080637db69ffa4f31f18f32878ddd2457e6857ztenghui updateDimensionInfo(res, false); 244abb7d134c02ac60091108c491dafb00877093170John Hoford } 245abb7d134c02ac60091108c491dafb00877093170John Hoford 24655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui @Override 24755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui public Drawable mutate() { 24855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui if (!mMutated && super.mutate() == this) { 24955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mVectorState = new VectorDrawableState(mVectorState); 25055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mMutated = true; 25155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 25255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui return this; 25355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 25455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 255727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette /** 256727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette * @hide 257727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette */ 258727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette public void clearMutated() { 259727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette super.clearMutated(); 260727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette mMutated = false; 261727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette } 262727cae197b123ef764a1f8fbe08a995b000d14c3Alan Viverette 263e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui Object getTargetByName(String name) { 26455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui return mVectorState.mVPathRenderer.mVGTargetsMap.get(name); 265e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 266e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 267abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 268abb7d134c02ac60091108c491dafb00877093170John Hoford public ConstantState getConstantState() { 26955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mVectorState.mChangingConfigurations = getChangingConfigurations(); 27055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui return mVectorState; 271abb7d134c02ac60091108c491dafb00877093170John Hoford } 272abb7d134c02ac60091108c491dafb00877093170John Hoford 2734554a6a5137d8e9bdfb623ad84ff344a48b7eb9dAlan Viverette @Override 274abb7d134c02ac60091108c491dafb00877093170John Hoford public void draw(Canvas canvas) { 27535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // We will offset the bounds for drawBitmap, so copyBounds() here instead 27635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // of getBounds(). 27735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui copyBounds(mTmpBounds); 27835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) { 27934c623cbf3677820c4170f24c5211f663dda91f7ztenghui // Nothing to draw 2801968201b44567262e7b2e382eee3d88990748d89Dan Sandler return; 2811968201b44567262e7b2e382eee3d88990748d89Dan Sandler } 2821968201b44567262e7b2e382eee3d88990748d89Dan Sandler 28335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // Color filters always override tint filters. 28435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter); 28535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui 28635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // The imageView can scale the canvas in different ways, in order to 28735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // avoid blurry scaling, we have to draw into a bitmap with exact pixel 28835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // size first. This bitmap size is determined by the bounds and the 28935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // canvas scale. 29035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui canvas.getMatrix(mTmpMatrix); 29135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mTmpMatrix.getValues(mTmpFloats); 29235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]); 29335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]); 29435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX); 29535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY); 29635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth); 29735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight); 29835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui 29935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui if (scaledWidth <= 0 || scaledHeight <= 0) { 30035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui return; 30135289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui } 30235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui 3030670f029a4e59448aa53b46a98e60dff6404f360ztenghui final int saveCount = canvas.save(); 30435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui canvas.translate(mTmpBounds.left, mTmpBounds.top); 305738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui 30635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // Handle RTL mirroring. 30735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui final boolean needMirroring = needMirroring(); 308738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui if (needMirroring) { 30935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui canvas.translate(mTmpBounds.width(), 0); 310738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui canvas.scale(-1.0f, 1.0f); 311738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui } 312482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui 31335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // At this point, canvas has been translated to the right position. 31435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // And we use this bound for the destination rect for the drawBitmap, so 31535289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui // we offset to (0, 0); 31635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mTmpBounds.offsetTo(0, 0); 317b07b086bd42181f62718a6394b56be3917b12511Alan Viverette 31835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight); 319482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui if (!mAllowCaching) { 32035289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mVectorState.updateCachedBitmap(scaledWidth, scaledHeight); 321482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } else { 3228490354dc651dd8f25036ef0dda7917fb33013edztenghui if (!mVectorState.canReuseCache()) { 32335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mVectorState.updateCachedBitmap(scaledWidth, scaledHeight); 324482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mVectorState.updateCacheStates(); 325482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 326482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 32735289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds); 3284b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette canvas.restoreToCount(saveCount); 329abb7d134c02ac60091108c491dafb00877093170John Hoford } 330abb7d134c02ac60091108c491dafb00877093170John Hoford 331abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public int getAlpha() { 333e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mVectorState.mVPathRenderer.getRootAlpha(); 334e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 335e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 336e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui @Override 337abb7d134c02ac60091108c491dafb00877093170John Hoford public void setAlpha(int alpha) { 3382af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) { 3392af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui mVectorState.mVPathRenderer.setRootAlpha(alpha); 340abb7d134c02ac60091108c491dafb00877093170John Hoford invalidateSelf(); 341abb7d134c02ac60091108c491dafb00877093170John Hoford } 342abb7d134c02ac60091108c491dafb00877093170John Hoford } 343abb7d134c02ac60091108c491dafb00877093170John Hoford 344abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 345abb7d134c02ac60091108c491dafb00877093170John Hoford public void setColorFilter(ColorFilter colorFilter) { 346b07b086bd42181f62718a6394b56be3917b12511Alan Viverette mColorFilter = colorFilter; 347fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette invalidateSelf(); 348abb7d134c02ac60091108c491dafb00877093170John Hoford } 349abb7d134c02ac60091108c491dafb00877093170John Hoford 350abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 351a74171190077d5ef8704a29442669e806447d560Alan Viverette public ColorFilter getColorFilter() { 352a74171190077d5ef8704a29442669e806447d560Alan Viverette return mColorFilter; 353a74171190077d5ef8704a29442669e806447d560Alan Viverette } 354a74171190077d5ef8704a29442669e806447d560Alan Viverette 355a74171190077d5ef8704a29442669e806447d560Alan Viverette @Override 356a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintList(ColorStateList tint) { 357b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette final VectorDrawableState state = mVectorState; 358a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette if (state.mTint != tint) { 359b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette state.mTint = tint; 360a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); 361a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette invalidateSelf(); 362a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette } 363a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette } 364b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 365a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette @Override 366a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette public void setTintMode(Mode tintMode) { 367a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette final VectorDrawableState state = mVectorState; 368a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette if (state.mTintMode != tintMode) { 369a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette state.mTintMode = tintMode; 370a426445dfdab43886dd894f2ba8a1d55bfcbb278Alan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); 371b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette invalidateSelf(); 372b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette } 373b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette } 374b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 375b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette @Override 376607bd848269fb802550e63aa61945790616f97a7Alan Viverette public boolean isStateful() { 377607bd848269fb802550e63aa61945790616f97a7Alan Viverette return super.isStateful() || (mVectorState != null && mVectorState.mTint != null 378607bd848269fb802550e63aa61945790616f97a7Alan Viverette && mVectorState.mTint.isStateful()); 379607bd848269fb802550e63aa61945790616f97a7Alan Viverette } 380607bd848269fb802550e63aa61945790616f97a7Alan Viverette 381607bd848269fb802550e63aa61945790616f97a7Alan Viverette @Override 382b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette protected boolean onStateChange(int[] stateSet) { 383b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette final VectorDrawableState state = mVectorState; 384b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette if (state.mTint != null && state.mTintMode != null) { 385b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 386607bd848269fb802550e63aa61945790616f97a7Alan Viverette invalidateSelf(); 387b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette return true; 388b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette } 389b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette return false; 390b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette } 391b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette 392b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette @Override 393abb7d134c02ac60091108c491dafb00877093170John Hoford public int getOpacity() { 394abb7d134c02ac60091108c491dafb00877093170John Hoford return PixelFormat.TRANSLUCENT; 395abb7d134c02ac60091108c491dafb00877093170John Hoford } 396abb7d134c02ac60091108c491dafb00877093170John Hoford 397abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 398abb7d134c02ac60091108c491dafb00877093170John Hoford public int getIntrinsicWidth() { 39995080637db69ffa4f31f18f32878ddd2457e6857ztenghui return mDpiScaledWidth; 400abb7d134c02ac60091108c491dafb00877093170John Hoford } 401abb7d134c02ac60091108c491dafb00877093170John Hoford 402abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 403abb7d134c02ac60091108c491dafb00877093170John Hoford public int getIntrinsicHeight() { 40495080637db69ffa4f31f18f32878ddd2457e6857ztenghui return mDpiScaledHeight; 405abb7d134c02ac60091108c491dafb00877093170John Hoford } 406abb7d134c02ac60091108c491dafb00877093170John Hoford 40787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette /** @hide */ 40887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette @Override 40987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette public Insets getOpticalInsets() { 41095080637db69ffa4f31f18f32878ddd2457e6857ztenghui return mDpiScaleInsets; 41195080637db69ffa4f31f18f32878ddd2457e6857ztenghui } 41295080637db69ffa4f31f18f32878ddd2457e6857ztenghui 41395080637db69ffa4f31f18f32878ddd2457e6857ztenghui /* 41495080637db69ffa4f31f18f32878ddd2457e6857ztenghui * Update the VectorDrawable dimension since the res can be in different Dpi now. 41595080637db69ffa4f31f18f32878ddd2457e6857ztenghui * Basically, when a new instance is created or getDimension() is called, we should update 41695080637db69ffa4f31f18f32878ddd2457e6857ztenghui * the current VectorDrawable's dimension information. 41795080637db69ffa4f31f18f32878ddd2457e6857ztenghui * Only after updateStateFromTypedArray() is called, we should called this and update the 41895080637db69ffa4f31f18f32878ddd2457e6857ztenghui * constant state's dpi info, i.e. updateConstantStateDensity == true. 41995080637db69ffa4f31f18f32878ddd2457e6857ztenghui */ 42095080637db69ffa4f31f18f32878ddd2457e6857ztenghui void updateDimensionInfo(@Nullable Resources res, boolean updateConstantStateDensity) { 42195080637db69ffa4f31f18f32878ddd2457e6857ztenghui if (res != null) { 42295080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int densityDpi = res.getDisplayMetrics().densityDpi; 42395080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int targetDensity = densityDpi == 0 ? DisplayMetrics.DENSITY_DEFAULT : densityDpi; 42495080637db69ffa4f31f18f32878ddd2457e6857ztenghui 42595080637db69ffa4f31f18f32878ddd2457e6857ztenghui if (updateConstantStateDensity) { 42695080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState.mVPathRenderer.mTargetDensity = targetDensity; 42795080637db69ffa4f31f18f32878ddd2457e6857ztenghui } else { 42895080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int constantStateDensity = mVectorState.mVPathRenderer.mTargetDensity; 42995080637db69ffa4f31f18f32878ddd2457e6857ztenghui if (targetDensity != constantStateDensity && constantStateDensity != 0) { 43095080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaledWidth = Bitmap.scaleFromDensity( 43195080637db69ffa4f31f18f32878ddd2457e6857ztenghui (int) mVectorState.mVPathRenderer.mBaseWidth, constantStateDensity, 43295080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 43395080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaledHeight = Bitmap.scaleFromDensity( 43495080637db69ffa4f31f18f32878ddd2457e6857ztenghui (int) mVectorState.mVPathRenderer.mBaseHeight,constantStateDensity, 43595080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 43695080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int left = Bitmap.scaleFromDensity( 43795080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState.mVPathRenderer.mOpticalInsets.left, constantStateDensity, 43895080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 43995080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int right = Bitmap.scaleFromDensity( 44095080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState.mVPathRenderer.mOpticalInsets.right, constantStateDensity, 44195080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 44295080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int top = Bitmap.scaleFromDensity( 44395080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState.mVPathRenderer.mOpticalInsets.top, constantStateDensity, 44495080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 44595080637db69ffa4f31f18f32878ddd2457e6857ztenghui final int bottom = Bitmap.scaleFromDensity( 44695080637db69ffa4f31f18f32878ddd2457e6857ztenghui mVectorState.mVPathRenderer.mOpticalInsets.bottom, constantStateDensity, 44795080637db69ffa4f31f18f32878ddd2457e6857ztenghui targetDensity); 44895080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaleInsets = Insets.of(left, top, right, bottom); 44995080637db69ffa4f31f18f32878ddd2457e6857ztenghui return; 45095080637db69ffa4f31f18f32878ddd2457e6857ztenghui } 45195080637db69ffa4f31f18f32878ddd2457e6857ztenghui } 45295080637db69ffa4f31f18f32878ddd2457e6857ztenghui } 45395080637db69ffa4f31f18f32878ddd2457e6857ztenghui // For all the other cases, like either res is null, constant state is not initialized or 45495080637db69ffa4f31f18f32878ddd2457e6857ztenghui // target density is the same as the constant state, we will just use the constant state 45595080637db69ffa4f31f18f32878ddd2457e6857ztenghui // dimensions. 45695080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaledWidth = (int) mVectorState.mVPathRenderer.mBaseWidth; 45795080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaledHeight = (int) mVectorState.mVPathRenderer.mBaseHeight; 45895080637db69ffa4f31f18f32878ddd2457e6857ztenghui mDpiScaleInsets = mVectorState.mVPathRenderer.mOpticalInsets; 45987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette } 46087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette 461abb7d134c02ac60091108c491dafb00877093170John Hoford @Override 4629453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette public boolean canApplyTheme() { 463d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme(); 4649453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette } 4659453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 4669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette @Override 4679453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette public void applyTheme(Theme t) { 4689453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette super.applyTheme(t); 4699453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 4709453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette final VectorDrawableState state = mVectorState; 47145c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette if (state == null) { 47245c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette return; 47345c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette } 47445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 47545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette if (state.mThemeAttrs != null) { 47645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette final TypedArray a = t.resolveAttributes( 47745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette state.mThemeAttrs, R.styleable.VectorDrawable); 478607bd848269fb802550e63aa61945790616f97a7Alan Viverette try { 479607bd848269fb802550e63aa61945790616f97a7Alan Viverette state.mCacheDirty = true; 480607bd848269fb802550e63aa61945790616f97a7Alan Viverette updateStateFromTypedArray(a); 48195080637db69ffa4f31f18f32878ddd2457e6857ztenghui updateDimensionInfo(t.getResources(), true /* update constant state */); 482607bd848269fb802550e63aa61945790616f97a7Alan Viverette } catch (XmlPullParserException e) { 483607bd848269fb802550e63aa61945790616f97a7Alan Viverette throw new RuntimeException(e); 484607bd848269fb802550e63aa61945790616f97a7Alan Viverette } finally { 485607bd848269fb802550e63aa61945790616f97a7Alan Viverette a.recycle(); 486607bd848269fb802550e63aa61945790616f97a7Alan Viverette } 48745c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette } 488607bd848269fb802550e63aa61945790616f97a7Alan Viverette 48945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette // Apply theme to contained color state list. 49045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette if (state.mTint != null && state.mTint.canApplyTheme()) { 491e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette state.mTint = state.mTint.obtainForTheme(t); 492607bd848269fb802550e63aa61945790616f97a7Alan Viverette } 493607bd848269fb802550e63aa61945790616f97a7Alan Viverette 494ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui final VPathRenderer path = state.mVPathRenderer; 4959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette if (path != null && path.canApplyTheme()) { 4969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette path.applyTheme(t); 4979453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette } 49845c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette 49945c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette // Update local state. 50045c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 5019453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette } 5029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 503fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount /** 504fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. 505fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount * This is used to calculate the path animation accuracy. 506fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount * 507fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount * @hide 508fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount */ 509fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount public float getPixelSize() { 510f2b1cff4e2b152a7c776a7a79e8225a591f97d3eAndreas Gampe if (mVectorState == null || mVectorState.mVPathRenderer == null || 511fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount mVectorState.mVPathRenderer.mBaseWidth == 0 || 512fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount mVectorState.mVPathRenderer.mBaseHeight == 0 || 513fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount mVectorState.mVPathRenderer.mViewportHeight == 0 || 514fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount mVectorState.mVPathRenderer.mViewportWidth == 0) { 515fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount return 1; // fall back to 1:1 pixel mapping. 516fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount } 517fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth; 518fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight; 519fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth; 520fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight; 521fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float scaleX = viewportWidth / intrinsicWidth; 522fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount float scaleY = viewportHeight / intrinsicHeight; 523fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount return Math.min(scaleX, scaleY); 524fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount } 525fd3c4744f265c5277e6e2641a18d5ec3dff19f6bGeorge Mount 5264b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette /** @hide */ 5274b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette public static VectorDrawable create(Resources resources, int rid) { 5284b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette try { 529874bcd82c223ce58c9d76edcf619b3988c672307ztenghui final XmlPullParser parser = resources.getXml(rid); 530874bcd82c223ce58c9d76edcf619b3988c672307ztenghui final AttributeSet attrs = Xml.asAttributeSet(parser); 531874bcd82c223ce58c9d76edcf619b3988c672307ztenghui int type; 532874bcd82c223ce58c9d76edcf619b3988c672307ztenghui while ((type=parser.next()) != XmlPullParser.START_TAG && 533874bcd82c223ce58c9d76edcf619b3988c672307ztenghui type != XmlPullParser.END_DOCUMENT) { 534874bcd82c223ce58c9d76edcf619b3988c672307ztenghui // Empty loop 535874bcd82c223ce58c9d76edcf619b3988c672307ztenghui } 536874bcd82c223ce58c9d76edcf619b3988c672307ztenghui if (type != XmlPullParser.START_TAG) { 537874bcd82c223ce58c9d76edcf619b3988c672307ztenghui throw new XmlPullParserException("No start tag found"); 538874bcd82c223ce58c9d76edcf619b3988c672307ztenghui } 5394b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette 5404b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette final VectorDrawable drawable = new VectorDrawable(); 541874bcd82c223ce58c9d76edcf619b3988c672307ztenghui drawable.inflate(resources, parser, attrs); 5424b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette 5434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette return drawable; 5444b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette } catch (XmlPullParserException e) { 5454b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette Log.e(LOGTAG, "parser error", e); 5464b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette } catch (IOException e) { 5474b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette Log.e(LOGTAG, "parser error", e); 5484b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette } 5494b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette return null; 5504b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette } 5514b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette 5522af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui private static int applyAlpha(int color, float alpha) { 5532af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui int alphaBytes = Color.alpha(color); 5542af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui color &= 0x00FFFFFF; 5552af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui color |= ((int) (alphaBytes * alpha)) << 24; 5562af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui return color; 5572af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui } 5582af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui 5599cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette @Override 5609cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme) 5619cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette throws XmlPullParserException, IOException { 562a95c8abb366d9c39450513335f550b56da13b30aztenghui final VectorDrawableState state = mVectorState; 563a95c8abb366d9c39450513335f550b56da13b30aztenghui final VPathRenderer pathRenderer = new VPathRenderer(); 564a95c8abb366d9c39450513335f550b56da13b30aztenghui state.mVPathRenderer = pathRenderer; 565a95c8abb366d9c39450513335f550b56da13b30aztenghui 566607bd848269fb802550e63aa61945790616f97a7Alan Viverette final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable); 5679cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette updateStateFromTypedArray(a); 5689cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette a.recycle(); 5699cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 570a95c8abb366d9c39450513335f550b56da13b30aztenghui state.mCacheDirty = true; 57155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui inflateInternal(res, parser, attrs, theme); 5729cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 5739cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 57495080637db69ffa4f31f18f32878ddd2457e6857ztenghui updateDimensionInfo(res, true /* update constant state */); 5759cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette } 5769cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 577a95c8abb366d9c39450513335f550b56da13b30aztenghui private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { 5789cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette final VectorDrawableState state = mVectorState; 579a95c8abb366d9c39450513335f550b56da13b30aztenghui final VPathRenderer pathRenderer = state.mVPathRenderer; 5809cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 5818e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette // Account for any configuration changes. 5828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= a.getChangingConfigurations(); 5838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 5849cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette // Extract the theme attributes, if any. 5859cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette state.mThemeAttrs = a.extractThemeAttrs(); 5869cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 5879cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); 5889cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette if (tintMode != -1) { 5899cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); 5909cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette } 5919cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 5929cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); 5939cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette if (tint != null) { 5949cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette state.mTint = tint; 5959cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette } 596738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui 597738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui state.mAutoMirrored = a.getBoolean( 598738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored); 599a95c8abb366d9c39450513335f550b56da13b30aztenghui 600a95c8abb366d9c39450513335f550b56da13b30aztenghui pathRenderer.mViewportWidth = a.getFloat( 601a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth); 602a95c8abb366d9c39450513335f550b56da13b30aztenghui pathRenderer.mViewportHeight = a.getFloat( 603a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight); 604a95c8abb366d9c39450513335f550b56da13b30aztenghui 605a95c8abb366d9c39450513335f550b56da13b30aztenghui if (pathRenderer.mViewportWidth <= 0) { 606a95c8abb366d9c39450513335f550b56da13b30aztenghui throw new XmlPullParserException(a.getPositionDescription() + 6071c4d8b2173bf4b5bbac94748959752599775628dztenghui "<vector> tag requires viewportWidth > 0"); 608a95c8abb366d9c39450513335f550b56da13b30aztenghui } else if (pathRenderer.mViewportHeight <= 0) { 609a95c8abb366d9c39450513335f550b56da13b30aztenghui throw new XmlPullParserException(a.getPositionDescription() + 6101c4d8b2173bf4b5bbac94748959752599775628dztenghui "<vector> tag requires viewportHeight > 0"); 611a95c8abb366d9c39450513335f550b56da13b30aztenghui } 612a95c8abb366d9c39450513335f550b56da13b30aztenghui 613a95c8abb366d9c39450513335f550b56da13b30aztenghui pathRenderer.mBaseWidth = a.getDimension( 614a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth); 615a95c8abb366d9c39450513335f550b56da13b30aztenghui pathRenderer.mBaseHeight = a.getDimension( 616a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight); 617a95c8abb366d9c39450513335f550b56da13b30aztenghui 618a95c8abb366d9c39450513335f550b56da13b30aztenghui if (pathRenderer.mBaseWidth <= 0) { 619a95c8abb366d9c39450513335f550b56da13b30aztenghui throw new XmlPullParserException(a.getPositionDescription() + 6201c4d8b2173bf4b5bbac94748959752599775628dztenghui "<vector> tag requires width > 0"); 621a95c8abb366d9c39450513335f550b56da13b30aztenghui } else if (pathRenderer.mBaseHeight <= 0) { 622a95c8abb366d9c39450513335f550b56da13b30aztenghui throw new XmlPullParserException(a.getPositionDescription() + 6231c4d8b2173bf4b5bbac94748959752599775628dztenghui "<vector> tag requires height > 0"); 624a95c8abb366d9c39450513335f550b56da13b30aztenghui } 6258490354dc651dd8f25036ef0dda7917fb33013edztenghui 62687e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetLeft = a.getDimensionPixelSize( 62787e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.VectorDrawable_opticalInsetLeft, pathRenderer.mOpticalInsets.left); 62887e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetTop = a.getDimensionPixelSize( 62987e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.VectorDrawable_opticalInsetTop, pathRenderer.mOpticalInsets.top); 63087e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetRight = a.getDimensionPixelSize( 63187e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.VectorDrawable_opticalInsetRight, pathRenderer.mOpticalInsets.right); 63287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette final int insetBottom = a.getDimensionPixelSize( 63387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette R.styleable.VectorDrawable_opticalInsetBottom, pathRenderer.mOpticalInsets.bottom); 63487e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette pathRenderer.mOpticalInsets = Insets.of(insetLeft, insetTop, insetRight, insetBottom); 63587e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette 6368490354dc651dd8f25036ef0dda7917fb33013edztenghui final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha, 6378490354dc651dd8f25036ef0dda7917fb33013edztenghui pathRenderer.getAlpha()); 6388490354dc651dd8f25036ef0dda7917fb33013edztenghui pathRenderer.setAlpha(alphaInFloat); 6398490354dc651dd8f25036ef0dda7917fb33013edztenghui 6405004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette final String name = a.getString(R.styleable.VectorDrawable_name); 6415004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette if (name != null) { 6425004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette pathRenderer.mRootName = name; 6435004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette pathRenderer.mVGTargetsMap.put(name, pathRenderer); 6448490354dc651dd8f25036ef0dda7917fb33013edztenghui } 6459cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette } 6469cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette 64755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs, 6488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette Theme theme) throws XmlPullParserException, IOException { 6498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette final VectorDrawableState state = mVectorState; 650a95c8abb366d9c39450513335f550b56da13b30aztenghui final VPathRenderer pathRenderer = state.mVPathRenderer; 651abb7d134c02ac60091108c491dafb00877093170John Hoford boolean noPathTag = true; 6529453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 6534d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Use a stack to help to build the group tree. 6544d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // The top of the stack is always the current group. 6554d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui final Stack<VGroup> groupStack = new Stack<VGroup>(); 6564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui groupStack.push(pathRenderer.mRootGroup); 657abb7d134c02ac60091108c491dafb00877093170John Hoford 658abb7d134c02ac60091108c491dafb00877093170John Hoford int eventType = parser.getEventType(); 659abb7d134c02ac60091108c491dafb00877093170John Hoford while (eventType != XmlPullParser.END_DOCUMENT) { 660abb7d134c02ac60091108c491dafb00877093170John Hoford if (eventType == XmlPullParser.START_TAG) { 6619453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette final String tagName = parser.getName(); 6624d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui final VGroup currentGroup = groupStack.peek(); 6634d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 664abb7d134c02ac60091108c491dafb00877093170John Hoford if (SHAPE_PATH.equals(tagName)) { 665a95c8abb366d9c39450513335f550b56da13b30aztenghui final VFullPath path = new VFullPath(); 6669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette path.inflate(res, attrs, theme); 6678d0d24f7a2b1a59060aa18926984491691d3c667ztenghui currentGroup.mChildren.add(path); 668e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (path.getPathName() != null) { 66955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 670e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 671abb7d134c02ac60091108c491dafb00877093170John Hoford noPathTag = false; 6728e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= path.mChangingConfigurations; 673a95c8abb366d9c39450513335f550b56da13b30aztenghui } else if (SHAPE_CLIP_PATH.equals(tagName)) { 674a95c8abb366d9c39450513335f550b56da13b30aztenghui final VClipPath path = new VClipPath(); 675a95c8abb366d9c39450513335f550b56da13b30aztenghui path.inflate(res, attrs, theme); 676a95c8abb366d9c39450513335f550b56da13b30aztenghui currentGroup.mChildren.add(path); 677a95c8abb366d9c39450513335f550b56da13b30aztenghui if (path.getPathName() != null) { 678a95c8abb366d9c39450513335f550b56da13b30aztenghui pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 679a95c8abb366d9c39450513335f550b56da13b30aztenghui } 680a95c8abb366d9c39450513335f550b56da13b30aztenghui state.mChangingConfigurations |= path.mChangingConfigurations; 6816d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui } else if (SHAPE_GROUP.equals(tagName)) { 6824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui VGroup newChildGroup = new VGroup(); 6834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui newChildGroup.inflate(res, attrs, theme); 6848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui currentGroup.mChildren.add(newChildGroup); 6854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui groupStack.push(newChildGroup); 686e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (newChildGroup.getGroupName() != null) { 68755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(), 68855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui newChildGroup); 689e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 6908e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette state.mChangingConfigurations |= newChildGroup.mChangingConfigurations; 691abb7d134c02ac60091108c491dafb00877093170John Hoford } 6924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } else if (eventType == XmlPullParser.END_TAG) { 6934d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui final String tagName = parser.getName(); 6944d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui if (SHAPE_GROUP.equals(tagName)) { 6954d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui groupStack.pop(); 6964d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 697abb7d134c02ac60091108c491dafb00877093170John Hoford } 698abb7d134c02ac60091108c491dafb00877093170John Hoford eventType = parser.next(); 699abb7d134c02ac60091108c491dafb00877093170John Hoford } 7009453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 7014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Print the tree out for debug. 7024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui if (DBG_VECTOR_DRAWABLE) { 7034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui printGroupTree(pathRenderer.mRootGroup, 0); 7046d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui } 7056d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui 706a95c8abb366d9c39450513335f550b56da13b30aztenghui if (noPathTag) { 7079453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette final StringBuffer tag = new StringBuffer(); 7089453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 709a95c8abb366d9c39450513335f550b56da13b30aztenghui if (tag.length() > 0) { 710a95c8abb366d9c39450513335f550b56da13b30aztenghui tag.append(" or "); 711abb7d134c02ac60091108c491dafb00877093170John Hoford } 712a95c8abb366d9c39450513335f550b56da13b30aztenghui tag.append(SHAPE_PATH); 7139453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 7149453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette throw new XmlPullParserException("no " + tag + " defined"); 715abb7d134c02ac60091108c491dafb00877093170John Hoford } 716abb7d134c02ac60091108c491dafb00877093170John Hoford } 717abb7d134c02ac60091108c491dafb00877093170John Hoford 7184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private void printGroupTree(VGroup currentGroup, int level) { 7194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui String indent = ""; 7208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < level; i++) { 7214d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui indent += " "; 7224d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 7234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Print the current node 7248d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName() 7254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui + " rotation is " + currentGroup.mRotate); 7268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString()); 7278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui // Then print all the children groups 7288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < currentGroup.mChildren.size(); i++) { 7298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Object child = currentGroup.mChildren.get(i); 7308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (child instanceof VGroup) { 7318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui printGroupTree((VGroup) child, level + 1); 7328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 7334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 7344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 7354d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 73655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui @Override 73755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui public int getChangingConfigurations() { 738e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette return super.getChangingConfigurations() | mVectorState.getChangingConfigurations(); 73955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 74055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 741482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui void setAllowCaching(boolean allowCaching) { 742482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mAllowCaching = allowCaching; 743482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 744482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui 745738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui private boolean needMirroring() { 746738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; 747738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui } 748738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui 749738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui @Override 750738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui public void setAutoMirrored(boolean mirrored) { 751738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui if (mVectorState.mAutoMirrored != mirrored) { 752738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui mVectorState.mAutoMirrored = mirrored; 753738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui invalidateSelf(); 754738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui } 755738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui } 756738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui 757738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui @Override 758738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui public boolean isAutoMirrored() { 759738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui return mVectorState.mAutoMirrored; 760738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui } 761738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui 7625c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette private static class VectorDrawableState extends ConstantState { 7639cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette int[] mThemeAttrs; 7645c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette int mChangingConfigurations; 765ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui VPathRenderer mVPathRenderer; 766607bd848269fb802550e63aa61945790616f97a7Alan Viverette ColorStateList mTint = null; 767607bd848269fb802550e63aa61945790616f97a7Alan Viverette Mode mTintMode = DEFAULT_TINT_MODE; 768738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui boolean mAutoMirrored; 7695c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette 770482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui Bitmap mCachedBitmap; 771482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui int[] mCachedThemeAttrs; 772482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui ColorStateList mCachedTint; 773482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui Mode mCachedTintMode; 774482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui int mCachedRootAlpha; 775670689af43358568bf2b5916284f1cac5762f428ztenghui boolean mCachedAutoMirrored; 776670689af43358568bf2b5916284f1cac5762f428ztenghui boolean mCacheDirty; 777b07b086bd42181f62718a6394b56be3917b12511Alan Viverette /** Temporary paint object used to draw cached bitmaps. */ 778b07b086bd42181f62718a6394b56be3917b12511Alan Viverette Paint mTempPaint; 779b07b086bd42181f62718a6394b56be3917b12511Alan Viverette 78055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // Deep copy for mutate() or implicitly mutate. 7815c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette public VectorDrawableState(VectorDrawableState copy) { 7825c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette if (copy != null) { 7839cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette mThemeAttrs = copy.mThemeAttrs; 7845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette mChangingConfigurations = copy.mChangingConfigurations; 785ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui mVPathRenderer = new VPathRenderer(copy.mVPathRenderer); 7866f6578e81c1df207da47e2e1337382341f271206Chet Haase if (copy.mVPathRenderer.mFillPaint != null) { 7876f6578e81c1df207da47e2e1337382341f271206Chet Haase mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint); 7886f6578e81c1df207da47e2e1337382341f271206Chet Haase } 7896f6578e81c1df207da47e2e1337382341f271206Chet Haase if (copy.mVPathRenderer.mStrokePaint != null) { 7906f6578e81c1df207da47e2e1337382341f271206Chet Haase mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint); 7916f6578e81c1df207da47e2e1337382341f271206Chet Haase } 792b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette mTint = copy.mTint; 793b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette mTintMode = copy.mTintMode; 794738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui mAutoMirrored = copy.mAutoMirrored; 7955c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 7965c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 7975c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette 79835289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter, 79935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui Rect originalBounds) { 8008490354dc651dd8f25036ef0dda7917fb33013edztenghui // The bitmap's size is the same as the bounds. 801b07b086bd42181f62718a6394b56be3917b12511Alan Viverette final Paint p = getPaint(filter); 80235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui canvas.drawBitmap(mCachedBitmap, null, originalBounds, p); 8038490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8048490354dc651dd8f25036ef0dda7917fb33013edztenghui 8058490354dc651dd8f25036ef0dda7917fb33013edztenghui public boolean hasTranslucentRoot() { 8068490354dc651dd8f25036ef0dda7917fb33013edztenghui return mVPathRenderer.getRootAlpha() < 255; 8078490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8088490354dc651dd8f25036ef0dda7917fb33013edztenghui 8098490354dc651dd8f25036ef0dda7917fb33013edztenghui /** 8108490354dc651dd8f25036ef0dda7917fb33013edztenghui * @return null when there is no need for alpha paint. 8118490354dc651dd8f25036ef0dda7917fb33013edztenghui */ 812b07b086bd42181f62718a6394b56be3917b12511Alan Viverette public Paint getPaint(ColorFilter filter) { 813b07b086bd42181f62718a6394b56be3917b12511Alan Viverette if (!hasTranslucentRoot() && filter == null) { 814b07b086bd42181f62718a6394b56be3917b12511Alan Viverette return null; 8158490354dc651dd8f25036ef0dda7917fb33013edztenghui } 816b07b086bd42181f62718a6394b56be3917b12511Alan Viverette 817b07b086bd42181f62718a6394b56be3917b12511Alan Viverette if (mTempPaint == null) { 818b07b086bd42181f62718a6394b56be3917b12511Alan Viverette mTempPaint = new Paint(); 819eec6164e6f6178343219bdedcb1e26779fae7f89ztenghui mTempPaint.setFilterBitmap(true); 820b07b086bd42181f62718a6394b56be3917b12511Alan Viverette } 821b07b086bd42181f62718a6394b56be3917b12511Alan Viverette mTempPaint.setAlpha(mVPathRenderer.getRootAlpha()); 822b07b086bd42181f62718a6394b56be3917b12511Alan Viverette mTempPaint.setColorFilter(filter); 823b07b086bd42181f62718a6394b56be3917b12511Alan Viverette return mTempPaint; 8248490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8258490354dc651dd8f25036ef0dda7917fb33013edztenghui 82635289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui public void updateCachedBitmap(int width, int height) { 8278490354dc651dd8f25036ef0dda7917fb33013edztenghui mCachedBitmap.eraseColor(Color.TRANSPARENT); 8288490354dc651dd8f25036ef0dda7917fb33013edztenghui Canvas tmpCanvas = new Canvas(mCachedBitmap); 82935289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mVPathRenderer.draw(tmpCanvas, width, height, null); 8308490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8318490354dc651dd8f25036ef0dda7917fb33013edztenghui 83235289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui public void createCachedBitmapIfNeeded(int width, int height) { 83335289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui if (mCachedBitmap == null || !canReuseBitmap(width, height)) { 83435289f12d6cb0f0db67489876c805ad4a3cbd5f6ztenghui mCachedBitmap = Bitmap.createBitmap(width, height, 8358490354dc651dd8f25036ef0dda7917fb33013edztenghui Bitmap.Config.ARGB_8888); 8369c13ed366f205d94b2f3f4ddc96b55b1b9faadbaztenghui mCacheDirty = true; 8378490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8388490354dc651dd8f25036ef0dda7917fb33013edztenghui 8398490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8408490354dc651dd8f25036ef0dda7917fb33013edztenghui 8418490354dc651dd8f25036ef0dda7917fb33013edztenghui public boolean canReuseBitmap(int width, int height) { 8428490354dc651dd8f25036ef0dda7917fb33013edztenghui if (width == mCachedBitmap.getWidth() 8438490354dc651dd8f25036ef0dda7917fb33013edztenghui && height == mCachedBitmap.getHeight()) { 8448490354dc651dd8f25036ef0dda7917fb33013edztenghui return true; 8458490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8468490354dc651dd8f25036ef0dda7917fb33013edztenghui return false; 8478490354dc651dd8f25036ef0dda7917fb33013edztenghui } 8488490354dc651dd8f25036ef0dda7917fb33013edztenghui 8498490354dc651dd8f25036ef0dda7917fb33013edztenghui public boolean canReuseCache() { 850670689af43358568bf2b5916284f1cac5762f428ztenghui if (!mCacheDirty 851670689af43358568bf2b5916284f1cac5762f428ztenghui && mCachedThemeAttrs == mThemeAttrs 852482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui && mCachedTint == mTint 853482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui && mCachedTintMode == mTintMode 854670689af43358568bf2b5916284f1cac5762f428ztenghui && mCachedAutoMirrored == mAutoMirrored 8558490354dc651dd8f25036ef0dda7917fb33013edztenghui && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { 856482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui return true; 857482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 858482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui return false; 859482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 860482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui 861482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui public void updateCacheStates() { 862482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui // Use shallow copy here and shallow comparison in canReuseCache(), 863482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui // likely hit cache miss more, but practically not much difference. 864482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mCachedThemeAttrs = mThemeAttrs; 865482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mCachedTint = mTint; 866482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mCachedTintMode = mTintMode; 867482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui mCachedRootAlpha = mVPathRenderer.getRootAlpha(); 868670689af43358568bf2b5916284f1cac5762f428ztenghui mCachedAutoMirrored = mAutoMirrored; 869670689af43358568bf2b5916284f1cac5762f428ztenghui mCacheDirty = false; 870482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui } 871482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui 872607bd848269fb802550e63aa61945790616f97a7Alan Viverette @Override 873607bd848269fb802550e63aa61945790616f97a7Alan Viverette public boolean canApplyTheme() { 87445c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette return mThemeAttrs != null 87545c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()) 87645c4bbbbce6bbad50a033efcba7948a23f1f117aAlan Viverette || (mTint != null && mTint.canApplyTheme()) 877d21fd9d1ccd2b525f9c004a6cd9ba19a645701abAlan Viverette || super.canApplyTheme(); 878607bd848269fb802550e63aa61945790616f97a7Alan Viverette } 879607bd848269fb802550e63aa61945790616f97a7Alan Viverette 88055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui public VectorDrawableState() { 88155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mVPathRenderer = new VPathRenderer(); 88255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 88355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 8845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette @Override 8855c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette public Drawable newDrawable() { 88695080637db69ffa4f31f18f32878ddd2457e6857ztenghui return new VectorDrawable(this, null); 8875c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 8885c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette 8895c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette @Override 8905c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette public Drawable newDrawable(Resources res) { 89195080637db69ffa4f31f18f32878ddd2457e6857ztenghui return new VectorDrawable(this, res); 8925c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 8935c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette 8945c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette @Override 8955c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette public int getChangingConfigurations() { 896e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette return mChangingConfigurations 897e0f95f39c5a669a48ee3ebb8dc45bf2d7ee940f1Alan Viverette | (mTint != null ? mTint.getChangingConfigurations() : 0); 8985c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 8995c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette } 9005c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette 901ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui private static class VPathRenderer { 9024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui /* Right now the internal data structure is organized as a tree. 9034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * Each node can be a group node, or a path. 9044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * A group node can have groups or paths as children, but a path node has 9054d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * no children. 9064d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * One example can be: 9074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * Root Group 9084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * / | \ 9094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * Group Path Group 9104d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * / \ | 9114d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * Path Path Path 9124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui * 9134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui */ 91455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // Variables that only used temporarily inside the draw() call, so there 91555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // is no need for deep copying. 9166f6578e81c1df207da47e2e1337382341f271206Chet Haase private final Path mPath; 9176f6578e81c1df207da47e2e1337382341f271206Chet Haase private final Path mRenderPath; 91855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private final Matrix mFinalPathMatrix = new Matrix(); 9194b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette 9204b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette private Paint mStrokePaint; 9214b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette private Paint mFillPaint; 922abb7d134c02ac60091108c491dafb00877093170John Hoford private PathMeasure mPathMeasure; 9234b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette 92455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui ///////////////////////////////////////////////////// 92555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 9268e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette private int mChangingConfigurations; 92755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private final VGroup mRootGroup; 928a95c8abb366d9c39450513335f550b56da13b30aztenghui float mBaseWidth = 0; 929a95c8abb366d9c39450513335f550b56da13b30aztenghui float mBaseHeight = 0; 930a95c8abb366d9c39450513335f550b56da13b30aztenghui float mViewportWidth = 0; 931a95c8abb366d9c39450513335f550b56da13b30aztenghui float mViewportHeight = 0; 93287e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette Insets mOpticalInsets = Insets.NONE; 9338490354dc651dd8f25036ef0dda7917fb33013edztenghui int mRootAlpha = 0xFF; 9348490354dc651dd8f25036ef0dda7917fb33013edztenghui String mRootName = null; 9359453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 93695080637db69ffa4f31f18f32878ddd2457e6857ztenghui int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; 93795080637db69ffa4f31f18f32878ddd2457e6857ztenghui 93855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>(); 939abb7d134c02ac60091108c491dafb00877093170John Hoford 940ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui public VPathRenderer() { 9414d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui mRootGroup = new VGroup(); 9426f6578e81c1df207da47e2e1337382341f271206Chet Haase mPath = new Path(); 9436f6578e81c1df207da47e2e1337382341f271206Chet Haase mRenderPath = new Path(); 944abb7d134c02ac60091108c491dafb00877093170John Hoford } 9459453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 9462af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui public void setRootAlpha(int alpha) { 9472af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui mRootAlpha = alpha; 9482af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui } 9492af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui 9502af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui public int getRootAlpha() { 9512af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui return mRootAlpha; 9522af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui } 9532af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui 9548490354dc651dd8f25036ef0dda7917fb33013edztenghui // setAlpha() and getAlpha() are used mostly for animation purpose, since 9558490354dc651dd8f25036ef0dda7917fb33013edztenghui // Animator like to use alpha from 0 to 1. 9568490354dc651dd8f25036ef0dda7917fb33013edztenghui public void setAlpha(float alpha) { 9578490354dc651dd8f25036ef0dda7917fb33013edztenghui setRootAlpha((int) (alpha * 255)); 9588490354dc651dd8f25036ef0dda7917fb33013edztenghui } 9598490354dc651dd8f25036ef0dda7917fb33013edztenghui 9608490354dc651dd8f25036ef0dda7917fb33013edztenghui @SuppressWarnings("unused") 9618490354dc651dd8f25036ef0dda7917fb33013edztenghui public float getAlpha() { 9628490354dc651dd8f25036ef0dda7917fb33013edztenghui return getRootAlpha() / 255.0f; 9638490354dc651dd8f25036ef0dda7917fb33013edztenghui } 9648490354dc651dd8f25036ef0dda7917fb33013edztenghui 965ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui public VPathRenderer(VPathRenderer copy) { 96655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); 9676f6578e81c1df207da47e2e1337382341f271206Chet Haase mPath = new Path(copy.mPath); 9686f6578e81c1df207da47e2e1337382341f271206Chet Haase mRenderPath = new Path(copy.mRenderPath); 969abb7d134c02ac60091108c491dafb00877093170John Hoford mBaseWidth = copy.mBaseWidth; 970abb7d134c02ac60091108c491dafb00877093170John Hoford mBaseHeight = copy.mBaseHeight; 9715eb5cde467081d1af628e5463ba55f110265a86fztenghui mViewportWidth = copy.mViewportWidth; 972abb7d134c02ac60091108c491dafb00877093170John Hoford mViewportHeight = copy.mViewportHeight; 97387e1938be8e6c2ac7e6163a63df5dd69633cc836Alan Viverette mOpticalInsets = copy.mOpticalInsets; 9748e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette mChangingConfigurations = copy.mChangingConfigurations; 97555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mRootAlpha = copy.mRootAlpha; 9768490354dc651dd8f25036ef0dda7917fb33013edztenghui mRootName = copy.mRootName; 97795080637db69ffa4f31f18f32878ddd2457e6857ztenghui mTargetDensity = copy.mTargetDensity; 9788490354dc651dd8f25036ef0dda7917fb33013edztenghui if (copy.mRootName != null) { 9798490354dc651dd8f25036ef0dda7917fb33013edztenghui mVGTargetsMap.put(copy.mRootName, this); 9808490354dc651dd8f25036ef0dda7917fb33013edztenghui } 981abb7d134c02ac60091108c491dafb00877093170John Hoford } 982abb7d134c02ac60091108c491dafb00877093170John Hoford 9839453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette public boolean canApplyTheme() { 9844d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // If one of the paths can apply theme, then return true; 9854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui return recursiveCanApplyTheme(mRootGroup); 9864d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 9874d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 9884d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private boolean recursiveCanApplyTheme(VGroup currentGroup) { 9894d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // We can do a tree traverse here, if there is one path return true, 9904d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // then we return true for the whole tree. 9918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final ArrayList<Object> children = currentGroup.mChildren; 9928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui 9938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < children.size(); i++) { 9948d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Object child = children.get(i); 9958d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (child instanceof VGroup) { 9968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VGroup childGroup = (VGroup) child; 9978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (childGroup.canApplyTheme() 9988d0d24f7a2b1a59060aa18926984491691d3c667ztenghui || recursiveCanApplyTheme(childGroup)) { 9998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui return true; 10008d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 10018d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } else if (child instanceof VPath) { 10028d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VPath childPath = (VPath) child; 10038d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (childPath.canApplyTheme()) { 10048d0d24f7a2b1a59060aa18926984491691d3c667ztenghui return true; 10058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 10064d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 10074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 10089453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette return false; 10099453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette } 10109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 10119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette public void applyTheme(Theme t) { 10124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Apply theme to every path of the tree. 10134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui recursiveApplyTheme(mRootGroup, t); 10144d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 10154d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 10164d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private void recursiveApplyTheme(VGroup currentGroup, Theme t) { 10174d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // We can do a tree traverse here, apply theme to all paths which 10184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // can apply theme. 10198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final ArrayList<Object> children = currentGroup.mChildren; 10208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < children.size(); i++) { 10218d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Object child = children.get(i); 10228d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (child instanceof VGroup) { 10238d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VGroup childGroup = (VGroup) child; 10248d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (childGroup.canApplyTheme()) { 10258d0d24f7a2b1a59060aa18926984491691d3c667ztenghui childGroup.applyTheme(t); 10268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 10278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui recursiveApplyTheme(childGroup, t); 10288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } else if (child instanceof VPath) { 10298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VPath childPath = (VPath) child; 10308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (childPath.canApplyTheme()) { 10318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui childPath.applyTheme(t); 10328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 10334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 10344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 1035abb7d134c02ac60091108c491dafb00877093170John Hoford } 1036abb7d134c02ac60091108c491dafb00877093170John Hoford 10374d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix, 1038b07b086bd42181f62718a6394b56be3917b12511Alan Viverette Canvas canvas, int w, int h, ColorFilter filter) { 10394d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Calculate current group's matrix by preConcat the parent's and 10404d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // and the current one on the top of the stack. 10414d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Basically the Mfinal = Mviewport * M0 * M1 * M2; 10424d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Mi the local matrix at level i of the group tree. 10434d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui currentGroup.mStackedMatrix.set(currentMatrix); 10444d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix); 10454d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1046054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui // Save the current clip information, which is local to this group. 1047054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui canvas.save(); 10488d0d24f7a2b1a59060aa18926984491691d3c667ztenghui // Draw the group tree in the same order as the XML file. 10498d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < currentGroup.mChildren.size(); i++) { 10508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Object child = currentGroup.mChildren.get(i); 10518d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (child instanceof VGroup) { 10528d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VGroup childGroup = (VGroup) child; 10538d0d24f7a2b1a59060aa18926984491691d3c667ztenghui drawGroupTree(childGroup, currentGroup.mStackedMatrix, 1054b07b086bd42181f62718a6394b56be3917b12511Alan Viverette canvas, w, h, filter); 10558d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } else if (child instanceof VPath) { 10568d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VPath childPath = (VPath) child; 1057b07b086bd42181f62718a6394b56be3917b12511Alan Viverette drawPath(currentGroup, childPath, canvas, w, h, filter); 10588d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 1059abb7d134c02ac60091108c491dafb00877093170John Hoford } 1060054a17caaa7cd36f4f4ba644088c4ccf5b9c06fbztenghui canvas.restore(); 10614d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 1062abb7d134c02ac60091108c491dafb00877093170John Hoford 1063b07b086bd42181f62718a6394b56be3917b12511Alan Viverette public void draw(Canvas canvas, int w, int h, ColorFilter filter) { 10644d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui // Travese the tree in pre-order to draw. 1065d538fa0fb21171d8256b7d800ae757757f4e3a44Andreas Gampe drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvas, w, h, filter); 1066abb7d134c02ac60091108c491dafb00877093170John Hoford } 1067abb7d134c02ac60091108c491dafb00877093170John Hoford 1068b07b086bd42181f62718a6394b56be3917b12511Alan Viverette private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h, 1069b07b086bd42181f62718a6394b56be3917b12511Alan Viverette ColorFilter filter) { 10708490354dc651dd8f25036ef0dda7917fb33013edztenghui final float scaleX = w / mViewportWidth; 10719d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui final float scaleY = h / mViewportHeight; 10729d59a76dd0e850558e83ef1a48fefd865fac1336ztenghui final float minScale = Math.min(scaleX, scaleY); 10739af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui final Matrix groupStackedMatrix = vGroup.mStackedMatrix; 1074abb7d134c02ac60091108c491dafb00877093170John Hoford 10759af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui mFinalPathMatrix.set(groupStackedMatrix); 10765a836f74df027bb568da17fbde4e641b6a56d2a9ztenghui mFinalPathMatrix.postScale(scaleX, scaleY); 1077abb7d134c02ac60091108c491dafb00877093170John Hoford 10789af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui final float matrixScale = getMatrixScale(groupStackedMatrix); 10799af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui if (matrixScale == 0) { 10809af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // When either x or y is scaled to 0, we don't need to draw anything. 10819af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui return; 10829af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui } 10838d0d24f7a2b1a59060aa18926984491691d3c667ztenghui vPath.toPath(mPath); 10848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final Path path = mPath; 1085abb7d134c02ac60091108c491dafb00877093170John Hoford 10868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mRenderPath.reset(); 10879453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 1088a95c8abb366d9c39450513335f550b56da13b30aztenghui if (vPath.isClipPath()) { 1089a95c8abb366d9c39450513335f550b56da13b30aztenghui mRenderPath.addPath(path, mFinalPathMatrix); 1090e9c01a40a2f0f0da195dfbb2909aaee5c005d1c6Chris Craik canvas.clipPath(mRenderPath); 10918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } else { 1092a95c8abb366d9c39450513335f550b56da13b30aztenghui VFullPath fullPath = (VFullPath) vPath; 1093a95c8abb366d9c39450513335f550b56da13b30aztenghui if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) { 1094a95c8abb366d9c39450513335f550b56da13b30aztenghui float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f; 1095a95c8abb366d9c39450513335f550b56da13b30aztenghui float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f; 1096a95c8abb366d9c39450513335f550b56da13b30aztenghui 1097a95c8abb366d9c39450513335f550b56da13b30aztenghui if (mPathMeasure == null) { 1098a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathMeasure = new PathMeasure(); 1099a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1100a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathMeasure.setPath(mPath, false); 1101a95c8abb366d9c39450513335f550b56da13b30aztenghui 1102a95c8abb366d9c39450513335f550b56da13b30aztenghui float len = mPathMeasure.getLength(); 1103a95c8abb366d9c39450513335f550b56da13b30aztenghui start = start * len; 1104a95c8abb366d9c39450513335f550b56da13b30aztenghui end = end * len; 1105a95c8abb366d9c39450513335f550b56da13b30aztenghui path.reset(); 1106a95c8abb366d9c39450513335f550b56da13b30aztenghui if (start > end) { 1107a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathMeasure.getSegment(start, len, path, true); 1108a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathMeasure.getSegment(0f, end, path, true); 1109a95c8abb366d9c39450513335f550b56da13b30aztenghui } else { 1110a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathMeasure.getSegment(start, end, path, true); 1111a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1112a95c8abb366d9c39450513335f550b56da13b30aztenghui path.rLineTo(0, 0); // fix bug in measure 1113a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1114a95c8abb366d9c39450513335f550b56da13b30aztenghui mRenderPath.addPath(path, mFinalPathMatrix); 1115a95c8abb366d9c39450513335f550b56da13b30aztenghui 1116a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui if (fullPath.mFillColor != Color.TRANSPARENT) { 11178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (mFillPaint == null) { 11188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mFillPaint = new Paint(); 11198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mFillPaint.setStyle(Paint.Style.FILL); 11208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mFillPaint.setAntiAlias(true); 112163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui } 1122b07b086bd42181f62718a6394b56be3917b12511Alan Viverette 1123b07b086bd42181f62718a6394b56be3917b12511Alan Viverette final Paint fillPaint = mFillPaint; 1124b07b086bd42181f62718a6394b56be3917b12511Alan Viverette fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha)); 1125b07b086bd42181f62718a6394b56be3917b12511Alan Viverette fillPaint.setColorFilter(filter); 1126b07b086bd42181f62718a6394b56be3917b12511Alan Viverette canvas.drawPath(mRenderPath, fillPaint); 11278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 112863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1129a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui if (fullPath.mStrokeColor != Color.TRANSPARENT) { 11308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (mStrokePaint == null) { 11318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mStrokePaint = new Paint(); 11328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mStrokePaint.setStyle(Paint.Style.STROKE); 11338d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mStrokePaint.setAntiAlias(true); 11348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 11354b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette 11368d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final Paint strokePaint = mStrokePaint; 1137a95c8abb366d9c39450513335f550b56da13b30aztenghui if (fullPath.mStrokeLineJoin != null) { 1138a95c8abb366d9c39450513335f550b56da13b30aztenghui strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin); 11398d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 1140abb7d134c02ac60091108c491dafb00877093170John Hoford 1141a95c8abb366d9c39450513335f550b56da13b30aztenghui if (fullPath.mStrokeLineCap != null) { 1142a95c8abb366d9c39450513335f550b56da13b30aztenghui strokePaint.setStrokeCap(fullPath.mStrokeLineCap); 11438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 114463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1145c4d651ec8a8c190c5df173166357c2fdf47472ceztenghui strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit); 1146b07b086bd42181f62718a6394b56be3917b12511Alan Viverette strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha)); 1147b07b086bd42181f62718a6394b56be3917b12511Alan Viverette strokePaint.setColorFilter(filter); 11489af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui final float finalStrokeScale = minScale * matrixScale; 11499af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale); 11508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui canvas.drawPath(mRenderPath, strokePaint); 115163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui } 1152abb7d134c02ac60091108c491dafb00877093170John Hoford } 1153abb7d134c02ac60091108c491dafb00877093170John Hoford } 11549af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui 11559af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui private float getMatrixScale(Matrix groupStackedMatrix) { 11569af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // Given unit vectors A = (0, 1) and B = (1, 0). 11579af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'. 11589af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)), 11599af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|); 11609af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0. 11619af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // 11629af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // For non-skew case, which is most of the cases, matrix scale is computing exactly the 11639af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // scale on x and y axis, and take the minimal of these two. 11649af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // For skew case, an unit square will mapped to a parallelogram. And this function will 11659af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui // return the minimal height of the 2 bases. 11669af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float[] unitVectors = new float[] {0, 1, 1, 0}; 11679af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui groupStackedMatrix.mapVectors(unitVectors); 11689af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]); 11699af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]); 11709af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1], 11719af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui unitVectors[2], unitVectors[3]); 11729af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float maxScale = MathUtils.max(scaleX, scaleY); 11739af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui 11749af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui float matrixScale = 0; 11759af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui if (maxScale > 0) { 11769af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui matrixScale = MathUtils.abs(crossProduct) / maxScale; 11779af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui } 11789af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui if (DBG_VECTOR_DRAWABLE) { 11799af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale); 11809af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui } 11819af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui return matrixScale; 11829af77a4ce22540726fbddd275f89e65fd1a1edf8ztenghui } 1183abb7d134c02ac60091108c491dafb00877093170John Hoford } 1184abb7d134c02ac60091108c491dafb00877093170John Hoford 1185a95c8abb366d9c39450513335f550b56da13b30aztenghui private static class VGroup { 118655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // mStackedMatrix is only used temporarily when drawing, it combines all 118755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // the parents' local matrices with the current one. 118855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui private final Matrix mStackedMatrix = new Matrix(); 118955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 119055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui ///////////////////////////////////////////////////// 119155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 11928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final ArrayList<Object> mChildren = new ArrayList<Object>(); 1193abb7d134c02ac60091108c491dafb00877093170John Hoford 119463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui private float mRotate = 0; 119563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui private float mPivotX = 0; 119663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui private float mPivotY = 0; 1197452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui private float mScaleX = 1; 1198452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui private float mScaleY = 1; 1199452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui private float mTranslateX = 0; 1200452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui private float mTranslateY = 0; 12014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 120255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // mLocalMatrix is updated based on the update of transformation information, 120355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // either parsed from the XML or by animation. 12044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui private final Matrix mLocalMatrix = new Matrix(); 12058e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette private int mChangingConfigurations; 120663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui private int[] mThemeAttrs; 1207e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui private String mGroupName = null; 1208e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 120955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) { 121055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mRotate = copy.mRotate; 121155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mPivotX = copy.mPivotX; 121255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mPivotY = copy.mPivotY; 121355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mScaleX = copy.mScaleX; 121455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mScaleY = copy.mScaleY; 121555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mTranslateX = copy.mTranslateX; 121655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mTranslateY = copy.mTranslateY; 121755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mThemeAttrs = copy.mThemeAttrs; 121855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mGroupName = copy.mGroupName; 121955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mChangingConfigurations = copy.mChangingConfigurations; 122055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui if (mGroupName != null) { 122155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui targetsMap.put(mGroupName, this); 122255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 122355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 122455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mLocalMatrix.set(copy.mLocalMatrix); 122555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 12268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui final ArrayList<Object> children = copy.mChildren; 12278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui for (int i = 0; i < children.size(); i++) { 12288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui Object copyChild = children.get(i); 12298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (copyChild instanceof VGroup) { 12308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui VGroup copyGroup = (VGroup) copyChild; 12318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mChildren.add(new VGroup(copyGroup, targetsMap)); 1232a95c8abb366d9c39450513335f550b56da13b30aztenghui } else { 1233a95c8abb366d9c39450513335f550b56da13b30aztenghui VPath newPath = null; 1234a95c8abb366d9c39450513335f550b56da13b30aztenghui if (copyChild instanceof VFullPath) { 1235a95c8abb366d9c39450513335f550b56da13b30aztenghui newPath = new VFullPath((VFullPath) copyChild); 1236a95c8abb366d9c39450513335f550b56da13b30aztenghui } else if (copyChild instanceof VClipPath) { 1237a95c8abb366d9c39450513335f550b56da13b30aztenghui newPath = new VClipPath((VClipPath) copyChild); 1238a95c8abb366d9c39450513335f550b56da13b30aztenghui } else { 1239a95c8abb366d9c39450513335f550b56da13b30aztenghui throw new IllegalStateException("Unknown object in the tree!"); 1240a95c8abb366d9c39450513335f550b56da13b30aztenghui } 12418d0d24f7a2b1a59060aa18926984491691d3c667ztenghui mChildren.add(newPath); 12428d0d24f7a2b1a59060aa18926984491691d3c667ztenghui if (newPath.mPathName != null) { 12438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui targetsMap.put(newPath.mPathName, newPath); 12448d0d24f7a2b1a59060aa18926984491691d3c667ztenghui } 124555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 124655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 124755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 124855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 124955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui public VGroup() { 125055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui } 125155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 1252a95c8abb366d9c39450513335f550b56da13b30aztenghui public String getGroupName() { 1253a95c8abb366d9c39450513335f550b56da13b30aztenghui return mGroupName; 1254a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1255a95c8abb366d9c39450513335f550b56da13b30aztenghui 1256a95c8abb366d9c39450513335f550b56da13b30aztenghui public Matrix getLocalMatrix() { 1257a95c8abb366d9c39450513335f550b56da13b30aztenghui return mLocalMatrix; 1258a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1259a95c8abb366d9c39450513335f550b56da13b30aztenghui 1260a95c8abb366d9c39450513335f550b56da13b30aztenghui public void inflate(Resources res, AttributeSet attrs, Theme theme) { 1261a95c8abb366d9c39450513335f550b56da13b30aztenghui final TypedArray a = obtainAttributes(res, theme, attrs, 1262a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawableGroup); 1263a95c8abb366d9c39450513335f550b56da13b30aztenghui updateStateFromTypedArray(a); 1264a95c8abb366d9c39450513335f550b56da13b30aztenghui a.recycle(); 1265a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1266a95c8abb366d9c39450513335f550b56da13b30aztenghui 1267a95c8abb366d9c39450513335f550b56da13b30aztenghui private void updateStateFromTypedArray(TypedArray a) { 1268a95c8abb366d9c39450513335f550b56da13b30aztenghui // Account for any configuration changes. 1269a95c8abb366d9c39450513335f550b56da13b30aztenghui mChangingConfigurations |= a.getChangingConfigurations(); 1270a95c8abb366d9c39450513335f550b56da13b30aztenghui 1271a95c8abb366d9c39450513335f550b56da13b30aztenghui // Extract the theme attributes, if any. 1272a95c8abb366d9c39450513335f550b56da13b30aztenghui mThemeAttrs = a.extractThemeAttrs(); 1273a95c8abb366d9c39450513335f550b56da13b30aztenghui 1274a95c8abb366d9c39450513335f550b56da13b30aztenghui mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate); 1275a95c8abb366d9c39450513335f550b56da13b30aztenghui mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX); 1276a95c8abb366d9c39450513335f550b56da13b30aztenghui mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY); 1277a95c8abb366d9c39450513335f550b56da13b30aztenghui mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX); 1278a95c8abb366d9c39450513335f550b56da13b30aztenghui mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY); 1279a95c8abb366d9c39450513335f550b56da13b30aztenghui mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX); 1280a95c8abb366d9c39450513335f550b56da13b30aztenghui mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY); 1281a95c8abb366d9c39450513335f550b56da13b30aztenghui 1282a95c8abb366d9c39450513335f550b56da13b30aztenghui final String groupName = a.getString(R.styleable.VectorDrawableGroup_name); 1283a95c8abb366d9c39450513335f550b56da13b30aztenghui if (groupName != null) { 1284a95c8abb366d9c39450513335f550b56da13b30aztenghui mGroupName = groupName; 1285a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1286a95c8abb366d9c39450513335f550b56da13b30aztenghui 1287a95c8abb366d9c39450513335f550b56da13b30aztenghui updateLocalMatrix(); 1288a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1289a95c8abb366d9c39450513335f550b56da13b30aztenghui 1290607bd848269fb802550e63aa61945790616f97a7Alan Viverette public boolean canApplyTheme() { 1291607bd848269fb802550e63aa61945790616f97a7Alan Viverette return mThemeAttrs != null; 1292607bd848269fb802550e63aa61945790616f97a7Alan Viverette } 1293607bd848269fb802550e63aa61945790616f97a7Alan Viverette 1294a95c8abb366d9c39450513335f550b56da13b30aztenghui public void applyTheme(Theme t) { 1295a95c8abb366d9c39450513335f550b56da13b30aztenghui if (mThemeAttrs == null) { 1296a95c8abb366d9c39450513335f550b56da13b30aztenghui return; 1297a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1298a95c8abb366d9c39450513335f550b56da13b30aztenghui 1299607bd848269fb802550e63aa61945790616f97a7Alan Viverette final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawableGroup); 1300a95c8abb366d9c39450513335f550b56da13b30aztenghui updateStateFromTypedArray(a); 1301a95c8abb366d9c39450513335f550b56da13b30aztenghui a.recycle(); 1302a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1303a95c8abb366d9c39450513335f550b56da13b30aztenghui 1304a95c8abb366d9c39450513335f550b56da13b30aztenghui private void updateLocalMatrix() { 1305a95c8abb366d9c39450513335f550b56da13b30aztenghui // The order we apply is the same as the 1306a95c8abb366d9c39450513335f550b56da13b30aztenghui // RenderNode.cpp::applyViewPropertyTransforms(). 1307a95c8abb366d9c39450513335f550b56da13b30aztenghui mLocalMatrix.reset(); 1308a95c8abb366d9c39450513335f550b56da13b30aztenghui mLocalMatrix.postTranslate(-mPivotX, -mPivotY); 1309a95c8abb366d9c39450513335f550b56da13b30aztenghui mLocalMatrix.postScale(mScaleX, mScaleY); 1310a95c8abb366d9c39450513335f550b56da13b30aztenghui mLocalMatrix.postRotate(mRotate, 0, 0); 1311a95c8abb366d9c39450513335f550b56da13b30aztenghui mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); 1312a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1313a95c8abb366d9c39450513335f550b56da13b30aztenghui 1314a95c8abb366d9c39450513335f550b56da13b30aztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 1315a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1316e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getRotation() { 1317e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mRotate; 1318e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1319e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1320a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1321e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setRotation(float rotation) { 1322e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (rotation != mRotate) { 1323e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mRotate = rotation; 1324e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1325e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1326e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1327e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1328a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1329e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getPivotX() { 1330e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mPivotX; 1331e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1332e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1333a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1334e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setPivotX(float pivotX) { 1335e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (pivotX != mPivotX) { 1336e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mPivotX = pivotX; 1337e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1338e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1339e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1340e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1341a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1342e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getPivotY() { 1343e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mPivotY; 1344e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1345e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1346a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1347e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setPivotY(float pivotY) { 1348e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (pivotY != mPivotY) { 1349e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mPivotY = pivotY; 1350e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1351e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1352e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1353e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1354a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1355e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getScaleX() { 1356e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mScaleX; 1357e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 13584d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1359a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1360e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setScaleX(float scaleX) { 1361e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (scaleX != mScaleX) { 1362e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mScaleX = scaleX; 1363e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1364e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1365e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1366e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1367a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1368e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getScaleY() { 1369e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mScaleY; 1370e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1371e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1372a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1373e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setScaleY(float scaleY) { 1374e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (scaleY != mScaleY) { 1375e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mScaleY = scaleY; 1376e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1377e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1378e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1379e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1380a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1381e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getTranslateX() { 1382e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mTranslateX; 1383e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1384e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1385a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1386e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setTranslateX(float translateX) { 1387e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (translateX != mTranslateX) { 1388e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mTranslateX = translateX; 1389e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1390e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1391e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1392e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1393a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1394e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public float getTranslateY() { 1395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mTranslateY; 1396e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1397e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1398a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1399e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui public void setTranslateY(float translateY) { 1400e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui if (translateY != mTranslateY) { 1401e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mTranslateY = translateY; 1402e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui updateLocalMatrix(); 1403e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1404e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1405a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1406e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1407a95c8abb366d9c39450513335f550b56da13b30aztenghui /** 1408a95c8abb366d9c39450513335f550b56da13b30aztenghui * Common Path information for clip path and normal path. 1409a95c8abb366d9c39450513335f550b56da13b30aztenghui */ 1410a95c8abb366d9c39450513335f550b56da13b30aztenghui private static class VPath { 1411a95c8abb366d9c39450513335f550b56da13b30aztenghui protected PathParser.PathDataNode[] mNodes = null; 1412a95c8abb366d9c39450513335f550b56da13b30aztenghui String mPathName; 1413a95c8abb366d9c39450513335f550b56da13b30aztenghui int mChangingConfigurations; 1414a95c8abb366d9c39450513335f550b56da13b30aztenghui 1415a95c8abb366d9c39450513335f550b56da13b30aztenghui public VPath() { 1416a95c8abb366d9c39450513335f550b56da13b30aztenghui // Empty constructor. 14174d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 14184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1419a95c8abb366d9c39450513335f550b56da13b30aztenghui public VPath(VPath copy) { 1420a95c8abb366d9c39450513335f550b56da13b30aztenghui mPathName = copy.mPathName; 1421a95c8abb366d9c39450513335f550b56da13b30aztenghui mChangingConfigurations = copy.mChangingConfigurations; 1422a95c8abb366d9c39450513335f550b56da13b30aztenghui mNodes = PathParser.deepCopyNodes(copy.mNodes); 14234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 14244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1425a95c8abb366d9c39450513335f550b56da13b30aztenghui public void toPath(Path path) { 1426a95c8abb366d9c39450513335f550b56da13b30aztenghui path.reset(); 1427a95c8abb366d9c39450513335f550b56da13b30aztenghui if (mNodes != null) { 1428a95c8abb366d9c39450513335f550b56da13b30aztenghui PathParser.PathDataNode.nodesToPath(mNodes, path); 1429a95c8abb366d9c39450513335f550b56da13b30aztenghui } 14304d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 14314d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1432a95c8abb366d9c39450513335f550b56da13b30aztenghui public String getPathName() { 1433a95c8abb366d9c39450513335f550b56da13b30aztenghui return mPathName; 14348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette } 14358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette 1436a95c8abb366d9c39450513335f550b56da13b30aztenghui public boolean canApplyTheme() { 1437a95c8abb366d9c39450513335f550b56da13b30aztenghui return false; 1438a95c8abb366d9c39450513335f550b56da13b30aztenghui } 143963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1440a95c8abb366d9c39450513335f550b56da13b30aztenghui public void applyTheme(Theme t) { 1441a95c8abb366d9c39450513335f550b56da13b30aztenghui } 144263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1443a95c8abb366d9c39450513335f550b56da13b30aztenghui public boolean isClipPath() { 1444a95c8abb366d9c39450513335f550b56da13b30aztenghui return false; 1445a95c8abb366d9c39450513335f550b56da13b30aztenghui } 144663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1447a95c8abb366d9c39450513335f550b56da13b30aztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 1448a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1449a95c8abb366d9c39450513335f550b56da13b30aztenghui public PathParser.PathDataNode[] getPathData() { 1450a95c8abb366d9c39450513335f550b56da13b30aztenghui return mNodes; 1451a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1452a95c8abb366d9c39450513335f550b56da13b30aztenghui 1453a95c8abb366d9c39450513335f550b56da13b30aztenghui @SuppressWarnings("unused") 1454a95c8abb366d9c39450513335f550b56da13b30aztenghui public void setPathData(PathParser.PathDataNode[] nodes) { 1455a95c8abb366d9c39450513335f550b56da13b30aztenghui if (!PathParser.canMorph(mNodes, nodes)) { 1456a95c8abb366d9c39450513335f550b56da13b30aztenghui // This should not happen in the middle of animation. 1457a95c8abb366d9c39450513335f550b56da13b30aztenghui mNodes = PathParser.deepCopyNodes(nodes); 1458a95c8abb366d9c39450513335f550b56da13b30aztenghui } else { 1459a95c8abb366d9c39450513335f550b56da13b30aztenghui PathParser.updateNodes(mNodes, nodes); 146063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui } 1461a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1462a95c8abb366d9c39450513335f550b56da13b30aztenghui } 146363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1464a95c8abb366d9c39450513335f550b56da13b30aztenghui /** 1465a95c8abb366d9c39450513335f550b56da13b30aztenghui * Clip path, which only has name and pathData. 1466a95c8abb366d9c39450513335f550b56da13b30aztenghui */ 14678490354dc651dd8f25036ef0dda7917fb33013edztenghui private static class VClipPath extends VPath { 1468a95c8abb366d9c39450513335f550b56da13b30aztenghui public VClipPath() { 1469a95c8abb366d9c39450513335f550b56da13b30aztenghui // Empty constructor. 14708e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette } 14714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1472a95c8abb366d9c39450513335f550b56da13b30aztenghui public VClipPath(VClipPath copy) { 1473a95c8abb366d9c39450513335f550b56da13b30aztenghui super(copy); 1474a95c8abb366d9c39450513335f550b56da13b30aztenghui } 14754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui 1476a95c8abb366d9c39450513335f550b56da13b30aztenghui public void inflate(Resources r, AttributeSet attrs, Theme theme) { 1477a95c8abb366d9c39450513335f550b56da13b30aztenghui final TypedArray a = obtainAttributes(r, theme, attrs, 1478a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawableClipPath); 14798e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette updateStateFromTypedArray(a); 148063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui a.recycle(); 148163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui } 148263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui 1483a95c8abb366d9c39450513335f550b56da13b30aztenghui private void updateStateFromTypedArray(TypedArray a) { 1484a95c8abb366d9c39450513335f550b56da13b30aztenghui // Account for any configuration changes. 1485a95c8abb366d9c39450513335f550b56da13b30aztenghui mChangingConfigurations |= a.getChangingConfigurations(); 1486a95c8abb366d9c39450513335f550b56da13b30aztenghui 14875004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name); 14885004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette if (pathName != null) { 14895004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette mPathName = pathName; 14905004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette } 14915004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette 14925004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData); 14935004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette if (pathData != null) { 14945004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette mNodes = PathParser.createNodesFromPathData(pathData); 14955004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette } 1496a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1497a95c8abb366d9c39450513335f550b56da13b30aztenghui 1498a95c8abb366d9c39450513335f550b56da13b30aztenghui @Override 1499a95c8abb366d9c39450513335f550b56da13b30aztenghui public boolean isClipPath() { 1500a95c8abb366d9c39450513335f550b56da13b30aztenghui return true; 15014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui } 1502abb7d134c02ac60091108c491dafb00877093170John Hoford } 1503abb7d134c02ac60091108c491dafb00877093170John Hoford 1504a95c8abb366d9c39450513335f550b56da13b30aztenghui /** 1505a95c8abb366d9c39450513335f550b56da13b30aztenghui * Normal path, which contains all the fill / paint information. 1506a95c8abb366d9c39450513335f550b56da13b30aztenghui */ 1507a95c8abb366d9c39450513335f550b56da13b30aztenghui private static class VFullPath extends VPath { 150855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui ///////////////////////////////////////////////////// 150955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui // Variables below need to be copied (deep copy if applicable) for mutation. 15109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette private int[] mThemeAttrs; 15119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 1512a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui int mStrokeColor = Color.TRANSPARENT; 1513abb7d134c02ac60091108c491dafb00877093170John Hoford float mStrokeWidth = 0; 15142e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui 1515a70b4742a7a0b2edc57cbbbf83d2c6d43ebc300dztenghui int mFillColor = Color.TRANSPARENT; 15162e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui float mStrokeAlpha = 1.0f; 1517abb7d134c02ac60091108c491dafb00877093170John Hoford int mFillRule; 15182e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui float mFillAlpha = 1.0f; 1519abb7d134c02ac60091108c491dafb00877093170John Hoford float mTrimPathStart = 0; 1520abb7d134c02ac60091108c491dafb00877093170John Hoford float mTrimPathEnd = 1; 1521abb7d134c02ac60091108c491dafb00877093170John Hoford float mTrimPathOffset = 0; 15229453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 15234b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette Paint.Cap mStrokeLineCap = Paint.Cap.BUTT; 15244b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette Paint.Join mStrokeLineJoin = Paint.Join.MITER; 1525abb7d134c02ac60091108c491dafb00877093170John Hoford float mStrokeMiterlimit = 4; 15269453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 1527a95c8abb366d9c39450513335f550b56da13b30aztenghui public VFullPath() { 15289453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette // Empty constructor. 15299453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette } 15309453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette 1531a95c8abb366d9c39450513335f550b56da13b30aztenghui public VFullPath(VFullPath copy) { 1532a95c8abb366d9c39450513335f550b56da13b30aztenghui super(copy); 153355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mThemeAttrs = copy.mThemeAttrs; 153455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 153555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mStrokeColor = copy.mStrokeColor; 153655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mStrokeWidth = copy.mStrokeWidth; 15372e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mStrokeAlpha = copy.mStrokeAlpha; 153855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mFillColor = copy.mFillColor; 153955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mFillRule = copy.mFillRule; 15402e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mFillAlpha = copy.mFillAlpha; 154155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mTrimPathStart = copy.mTrimPathStart; 154255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mTrimPathEnd = copy.mTrimPathEnd; 154355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mTrimPathOffset = copy.mTrimPathOffset; 154455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui 154555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mStrokeLineCap = copy.mStrokeLineCap; 154655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mStrokeLineJoin = copy.mStrokeLineJoin; 154755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui mStrokeMiterlimit = copy.mStrokeMiterlimit; 1548abb7d134c02ac60091108c491dafb00877093170John Hoford } 1549abb7d134c02ac60091108c491dafb00877093170John Hoford 15507f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) { 15517f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette switch (id) { 15527f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINECAP_BUTT: 15537f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Cap.BUTT; 15547f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINECAP_ROUND: 15557f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Cap.ROUND; 15567f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINECAP_SQUARE: 15577f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Cap.SQUARE; 15587f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette default: 15597f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return defValue; 15607f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette } 15617f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette } 15627f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette 15637f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) { 15647f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette switch (id) { 15657f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINEJOIN_MITER: 15667f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Join.MITER; 15677f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINEJOIN_ROUND: 15687f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Join.ROUND; 15697f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette case LINEJOIN_BEVEL: 15707f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return Paint.Join.BEVEL; 15717f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette default: 15727f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette return defValue; 15737f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette } 15747f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette } 15757f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette 1576a95c8abb366d9c39450513335f550b56da13b30aztenghui @Override 1577a95c8abb366d9c39450513335f550b56da13b30aztenghui public boolean canApplyTheme() { 1578a95c8abb366d9c39450513335f550b56da13b30aztenghui return mThemeAttrs != null; 1579eb034fbca40006c55db143047eb628c4b657730aztenghui } 1580eb034fbca40006c55db143047eb628c4b657730aztenghui 1581a95c8abb366d9c39450513335f550b56da13b30aztenghui public void inflate(Resources r, AttributeSet attrs, Theme theme) { 1582a95c8abb366d9c39450513335f550b56da13b30aztenghui final TypedArray a = obtainAttributes(r, theme, attrs, 1583a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath); 1584a95c8abb366d9c39450513335f550b56da13b30aztenghui updateStateFromTypedArray(a); 1585a95c8abb366d9c39450513335f550b56da13b30aztenghui a.recycle(); 1586a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1587a95c8abb366d9c39450513335f550b56da13b30aztenghui 1588a95c8abb366d9c39450513335f550b56da13b30aztenghui private void updateStateFromTypedArray(TypedArray a) { 1589a95c8abb366d9c39450513335f550b56da13b30aztenghui // Account for any configuration changes. 1590a95c8abb366d9c39450513335f550b56da13b30aztenghui mChangingConfigurations |= a.getChangingConfigurations(); 1591a95c8abb366d9c39450513335f550b56da13b30aztenghui 1592a95c8abb366d9c39450513335f550b56da13b30aztenghui // Extract the theme attributes, if any. 1593a95c8abb366d9c39450513335f550b56da13b30aztenghui mThemeAttrs = a.extractThemeAttrs(); 1594a95c8abb366d9c39450513335f550b56da13b30aztenghui 15955004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette final String pathName = a.getString(R.styleable.VectorDrawablePath_name); 15965004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette if (pathName != null) { 15975004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette mPathName = pathName; 15985004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette } 15995004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette 16005004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData); 16015004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette if (pathData != null) { 16025004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette mNodes = PathParser.createNodesFromPathData(pathData); 16035004032ebc2aee97c5884b7f91cc33d2f98ae8b5Alan Viverette } 1604a95c8abb366d9c39450513335f550b56da13b30aztenghui 1605a95c8abb366d9c39450513335f550b56da13b30aztenghui mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor, 1606a95c8abb366d9c39450513335f550b56da13b30aztenghui mFillColor); 16072e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, 16082e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mFillAlpha); 1609a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeLineCap = getStrokeLineCap(a.getInt( 1610a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap); 1611a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeLineJoin = getStrokeLineJoin(a.getInt( 1612a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin); 1613a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeMiterlimit = a.getFloat( 1614a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit); 1615a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor, 1616a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeColor); 16172e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha, 16182e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mStrokeAlpha); 1619a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 1620a95c8abb366d9c39450513335f550b56da13b30aztenghui mStrokeWidth); 1621a95c8abb366d9c39450513335f550b56da13b30aztenghui mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1622a95c8abb366d9c39450513335f550b56da13b30aztenghui mTrimPathEnd); 1623a95c8abb366d9c39450513335f550b56da13b30aztenghui mTrimPathOffset = a.getFloat( 1624a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset); 1625a95c8abb366d9c39450513335f550b56da13b30aztenghui mTrimPathStart = a.getFloat( 1626a95c8abb366d9c39450513335f550b56da13b30aztenghui R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart); 1627a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1628a95c8abb366d9c39450513335f550b56da13b30aztenghui 1629a95c8abb366d9c39450513335f550b56da13b30aztenghui @Override 1630a95c8abb366d9c39450513335f550b56da13b30aztenghui public void applyTheme(Theme t) { 1631a95c8abb366d9c39450513335f550b56da13b30aztenghui if (mThemeAttrs == null) { 1632a95c8abb366d9c39450513335f550b56da13b30aztenghui return; 1633a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1634a95c8abb366d9c39450513335f550b56da13b30aztenghui 1635607bd848269fb802550e63aa61945790616f97a7Alan Viverette final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath); 1636a95c8abb366d9c39450513335f550b56da13b30aztenghui updateStateFromTypedArray(a); 1637a95c8abb366d9c39450513335f550b56da13b30aztenghui a.recycle(); 1638a95c8abb366d9c39450513335f550b56da13b30aztenghui } 1639a95c8abb366d9c39450513335f550b56da13b30aztenghui 1640a95c8abb366d9c39450513335f550b56da13b30aztenghui /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 1641eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1642dbcccffc3760f702887faa95b2748125bac88a89ztenghui int getStrokeColor() { 1643e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mStrokeColor; 1644e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1645e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1646eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1647dbcccffc3760f702887faa95b2748125bac88a89ztenghui void setStrokeColor(int strokeColor) { 1648e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mStrokeColor = strokeColor; 1649e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1650e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1651eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1652e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui float getStrokeWidth() { 1653e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mStrokeWidth; 1654e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1655e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1656eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1657e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui void setStrokeWidth(float strokeWidth) { 1658e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mStrokeWidth = strokeWidth; 1659e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1660e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1661eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1662dbcccffc3760f702887faa95b2748125bac88a89ztenghui float getStrokeAlpha() { 16632e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui return mStrokeAlpha; 16642e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui } 16652e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui 16662e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui @SuppressWarnings("unused") 1667dbcccffc3760f702887faa95b2748125bac88a89ztenghui void setStrokeAlpha(float strokeAlpha) { 16682e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mStrokeAlpha = strokeAlpha; 16692e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui } 16702e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui 16712e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui @SuppressWarnings("unused") 1672dbcccffc3760f702887faa95b2748125bac88a89ztenghui int getFillColor() { 1673e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mFillColor; 1674e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1675e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1676eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1677dbcccffc3760f702887faa95b2748125bac88a89ztenghui void setFillColor(int fillColor) { 1678e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mFillColor = fillColor; 1679e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1680e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1681eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1682dbcccffc3760f702887faa95b2748125bac88a89ztenghui float getFillAlpha() { 16832e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui return mFillAlpha; 16842e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui } 16852e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui 16862e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui @SuppressWarnings("unused") 1687dbcccffc3760f702887faa95b2748125bac88a89ztenghui void setFillAlpha(float fillAlpha) { 16882e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui mFillAlpha = fillAlpha; 16892e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui } 16902e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui 16912e17d2b232e11b3ec246c704d8c4707c8fd863faztenghui @SuppressWarnings("unused") 1692e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui float getTrimPathStart() { 1693e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mTrimPathStart; 1694e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1695e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1696eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1697e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui void setTrimPathStart(float trimPathStart) { 1698e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mTrimPathStart = trimPathStart; 1699e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1700e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1701eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1702e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui float getTrimPathEnd() { 1703e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mTrimPathEnd; 1704e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1705e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1706eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1707e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui void setTrimPathEnd(float trimPathEnd) { 1708e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mTrimPathEnd = trimPathEnd; 1709e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1710e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1711eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1712e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui float getTrimPathOffset() { 1713e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui return mTrimPathOffset; 1714e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1715e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui 1716eb034fbca40006c55db143047eb628c4b657730aztenghui @SuppressWarnings("unused") 1717e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui void setTrimPathOffset(float trimPathOffset) { 1718e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui mTrimPathOffset = trimPathOffset; 1719e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui } 1720abb7d134c02ac60091108c491dafb00877093170John Hoford } 1721abb7d134c02ac60091108c491dafb00877093170John Hoford} 1722