VectorDrawable.java revision 34c623cbf3677820c4170f24c5211f663dda91f7
1e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy/* 2e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Copyright (C) 2014 The Android Open Source Project 3e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 4e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * in compliance with the License. You may obtain a copy of the License at 6e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 7e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * http://www.apache.org/licenses/LICENSE-2.0 8e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 9e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * Unless required by applicable law or agreed to in writing, software distributed under the License 10e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * or implied. See the License for the specific language governing permissions and limitations under 12e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * the License. 13e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy */ 14e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 15e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guypackage android.graphics.drawable; 16e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy 1785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyimport android.annotation.NonNull; 18e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.content.res.ColorStateList; 19e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.content.res.Resources; 20e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.content.res.Resources.Theme; 21e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.content.res.TypedArray; 22e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.Bitmap; 23bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guyimport android.graphics.Canvas; 24694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guyimport android.graphics.Color; 255cbbce535744b89df5ecea95de21ee3733298260Romain Guyimport android.graphics.ColorFilter; 265cbbce535744b89df5ecea95de21ee3733298260Romain Guyimport android.graphics.Matrix; 27e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guyimport android.graphics.Paint; 2885bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyimport android.graphics.Path; 295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyimport android.graphics.PathMeasure; 305b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guyimport android.graphics.PixelFormat; 3185bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guyimport android.graphics.PorterDuffColorFilter; 320fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guyimport android.graphics.Rect; 33a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guyimport android.graphics.Region; 34e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.graphics.PorterDuff.Mode; 35e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guyimport android.util.ArrayMap; 369d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport android.util.AttributeSet; 379d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport android.util.LayoutDirection; 389d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport android.util.Log; 399d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport android.util.PathParser; 409d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport android.util.Xml; 419d5316e3f56d138504565ff311145ac01621dff4Romain Guy 42759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyimport com.android.internal.R; 43759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy 44759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guyimport org.xmlpull.v1.XmlPullParser; 45dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guyimport org.xmlpull.v1.XmlPullParserException; 46dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 47dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guyimport java.io.IOException; 489d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport java.util.ArrayList; 499d5316e3f56d138504565ff311145ac01621dff4Romain Guyimport java.util.Stack; 509d5316e3f56d138504565ff311145ac01621dff4Romain Guy 519d5316e3f56d138504565ff311145ac01621dff4Romain Guy/** 52889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * This lets you create a drawable based on an XML vector graphic. It can be 53889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * defined in an XML file with the <code><vector></code> element. 54889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <p/> 55889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * The vector drawable has the following elements: 56889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <p/> 57889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <dt><code><vector></code></dt> 58889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <dl> 59889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <dd>Used to defined a vector drawable 60889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <dl> 61026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy * <dt><code>android:name</code></dt> 62026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy * <dd>Defines the name of this vector drawable.</dd> 63026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy * <dt><code>android:width</code></dt> 64b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>Used to defined the intrinsic width of the drawable. 65b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * This support all the dimension units, normally specified with dp.</dd> 66b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:height</code></dt> 67b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>Used to defined the intrinsic height the drawable. 68b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * This support all the dimension units, normally specified with dp.</dd> 69b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:viewportWidth</code></dt> 70b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>Used to defined the width of the viewport space. Viewport is basically 71b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * the virtual canvas where the paths are drawn on.</dd> 72b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:viewportHeight</code></dt> 73b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>Used to defined the height of the viewport space. Viewport is basically 74b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * the virtual canvas where the paths are drawn on.</dd> 75b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:tint</code></dt> 76026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy * <dd>The color to apply to the drawable as a tint. By default, no tint is applied.</dd> 77e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * <dt><code>android:tintMode</code></dt> 7887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * <dd>The Porter-Duff blending mode for the tint color. The default value is src_in.</dd> 7987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * <dt><code>android:autoMirrored</code></dt> 8087a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy * <dd>Indicates if the drawable needs to be mirrored when its layout direction is 81f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy * RTL (right-to-left).</dd> 82b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:alpha</code></dt> 83b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>The opacity of this drawable.</dd> 84b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * </dl></dd> 85b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * </dl> 86b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * 87b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dl> 88b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code><group></code></dt> 89b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>Defines a group of paths or subgroups, plus transformation information. 90b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * The transformations are defined in the same coordinates as the viewport. 91b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * And the transformations are applied in the order of scale, rotate then translate. 92b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dl> 93b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:name</code></dt> 94f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy * <dd>Defines the name of the group.</dd> 95f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy * <dt><code>android:rotation</code></dt> 96889f8d1403761d5668115ced6cbb3f767cfe966dRomain Guy * <dd>The degrees of rotation of the group.</dd> 97b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dt><code>android:pivotX</code></dt> 98b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * <dd>The X coordinate of the pivot for the scale and rotation of the group. 99b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy * This is defined in the viewport space.</dd> 100d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy * <dt><code>android:pivotY</code></dt> 101d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy * <dd>The Y coordinate of the pivot for the scale and rotation of the group. 102f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * This is defined in the viewport space.</dd> 103f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dt><code>android:scaleX</code></dt> 104f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dd>The amount of scale on the X Coordinate.</dd> 105f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dt><code>android:scaleY</code></dt> 106fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy * <dd>The amount of scale on the Y coordinate.</dd> 10706f96e2652e4855b6520ad9dd70583677605b79aRomain Guy * <dt><code>android:translateX</code></dt> 108db1938e0e6ef816e228c815adccebd5cb05f2aa8Romain Guy * <dd>The amount of translation on the X coordinate. 1091e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy * This is defined in the viewport space.</dd> 110026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy * <dt><code>android:translateY</code></dt> 111ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * <dd>The amount of translation on the Y coordinate. 112ac670c0433d19397d4e36ced2110475b6f54fe26Romain Guy * This is defined in the viewport space.</dd> 113ae5575b3421c8fbe590ab046d7d5f2b36ecfd821Romain Guy * </dl></dd> 114e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * </dl> 115e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * 11685bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy * <dl> 11729d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy * <dt><code><path></code></dt> 11829d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy * <dd>Defines paths to be drawn. 119e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * <dl> 120e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * <dt><code>android:name</code></dt> 121f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dd>Defines the name of the path.</dd> 122f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dt><code>android:pathData</code></dt> 123f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dd>Defines path string. This is using exactly same format as "d" attribute 124f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * in the SVG's path data. This is defined in the viewport space.</dd> 12585bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy * <dt><code>android:fillColor</code></dt> 12608ae317c21ec3086b5017672bba87420cc38a407Romain Guy * <dd>Defines the color to fill the path (none if not present).</dd> 127260e102162322958cf17dbd895cd6bd30dc87e32Romain Guy * <dt><code>android:strokeColor</code></dt> 128bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * <dd>Defines the color to draw the path outline (none if not present).</dd> 129bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * <dt><code>android:strokeWidth</code></dt> 130bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * <dd>The width a path stroke.</dd> 131eb99356a0548684a501766e6a524529ab93304c8Romain Guy * <dt><code>android:strokeAlpha</code></dt> 132eb99356a0548684a501766e6a524529ab93304c8Romain Guy * <dd>The opacity of a path stroke.</dd> 133eb99356a0548684a501766e6a524529ab93304c8Romain Guy * <dt><code>android:fillAlpha</code></dt> 134746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy * <dd>The opacity to fill the path with.</dd> 135746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy * <dt><code>android:trimPathStart</code></dt> 136e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * <dd>The fraction of the path to trim from the start, in the range from 0 to 1.</dd> 137e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy * <dt><code>android:trimPathEnd</code></dt> 1386b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * <dd>The fraction of the path to trim from the end, in the range from 0 to 1.</dd> 139fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy * <dt><code>android:trimPathOffset</code></dt> 140fe48f65922d4a3cc4aefe058cee5acec51504a20Romain Guy * <dd>Shift trim region (allows showed region to include the start and end), in the range 1418aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy * from 0 to 1.</dd> 1428aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy * <dt><code>android:strokeLineCap</code></dt> 1438fb954263dd2f918ad339045cc6d82e346515599Romain Guy * <dd>Sets the linecap for a stroked path: butt, round, square.</dd> 144f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * <dt><code>android:strokeLineJoin</code></dt> 145fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy * <dd>Sets the lineJoin for a stroked path: miter,round,bevel.</dd> 146fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy * <dt><code>android:strokeMiterLimit</code></dt> 147d90f23e24a4d1768d5a7ed0e7072e67af6330a45Romain Guy * <dd>Sets the Miter limit for a stroked path.</dd> 148bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * </dl></dd> 1496b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * </dl> 150746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy * 1516b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * <dl> 1526b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * <dt><code><clip-path></code></dt> 1536b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy * <dd>Defines path to be the current clip. Note that the clip path only apply to 154bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * the current group and its children. 1550d200833fdc53f9796698f97c18cefc4a1b82df2Chet Haase * <dl> 1560d200833fdc53f9796698f97c18cefc4a1b82df2Chet Haase * <dt><code>android:name</code></dt> 157b82da65cb1601be504241f36778395cd6cb9f87bRomain Guy * <dd>Defines the name of the clip path.</dd> 158bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * <dt><code>android:pathData</code></dt> 159bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * <dd>Defines clip path string. This is using exactly same format as "d" attribute 160b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * in the SVG's path data.</dd> 161b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * </dl></dd> 162b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * </dl> 163b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * <li>Here is a simple VectorDrawable in this vectordrawable.xml file. 164b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * <pre> 165a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy * <vector xmlns:android="http://schemas.android.com/apk/res/android" 166a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy * android:height="64dp" 167a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy * android:width="64dp" 168a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy * android:viewportHeight="600" 169a07105b7d2a27e6d69407bf96ddb773bddb5e553Romain Guy * android:viewportWidth="600" > 170b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * <group 171b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * android:name="rotationGroup" 172c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy * android:pivotX="300.0" 173c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy * android:pivotY="300.0" 174e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy * android:rotation="45.0" > 175e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy * <path 176e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy * android:name="v" 177e190aa69756aecfaffabdd4c6d32cb6b3220d842Romain Guy * android:fillColor="#000000" 178c15008e72ec00ca20a271c3006dac649fd07533bRomain Guy * android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" /> 179b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * </group> 180b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * </vector> 1816c319ca1275c8db892c39b48fc54864c949f9171Romain Guy * </pre></li> 182da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy */ 183da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy 184da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guypublic class VectorDrawable extends Drawable { 185da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final String LOGTAG = VectorDrawable.class.getSimpleName(); 186da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy 187da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final String SHAPE_CLIP_PATH = "clip-path"; 18850c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy private static final String SHAPE_GROUP = "group"; 189da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final String SHAPE_PATH = "path"; 190da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final String SHAPE_VECTOR = "vector"; 1916c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 1926c319ca1275c8db892c39b48fc54864c949f9171Romain Guy private static final int LINECAP_BUTT = 0; 1936c319ca1275c8db892c39b48fc54864c949f9171Romain Guy private static final int LINECAP_ROUND = 1; 1946c319ca1275c8db892c39b48fc54864c949f9171Romain Guy private static final int LINECAP_SQUARE = 2; 1956c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 196eb99356a0548684a501766e6a524529ab93304c8Romain Guy private static final int LINEJOIN_MITER = 0; 197da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final int LINEJOIN_ROUND = 1; 198da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final int LINEJOIN_BEVEL = 2; 199746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy 200da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private static final boolean DBG_VECTOR_DRAWABLE = false; 201f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy 202f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy private VectorDrawableState mVectorState; 20342f3a4b7c35dd1ea1922356eb3611af8cde05179Romain Guy 20403750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy private PorterDuffColorFilter mTintFilter; 20550c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy private ColorFilter mColorFilter; 20650c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy 20750c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy private boolean mMutated; 20850c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy 20950c0f093d942a59d4e01b2c76d26c0e9d6ed796cRomain Guy // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise, 210da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy // caching the bitmap by default is allowed. 211da8532c6f48b4c10b5e2ccb9e08690341efa1616Romain Guy private boolean mAllowCaching = true; 2126c319ca1275c8db892c39b48fc54864c949f9171Romain Guy 2136c319ca1275c8db892c39b48fc54864c949f9171Romain Guy public VectorDrawable() { 2146c319ca1275c8db892c39b48fc54864c949f9171Romain Guy mVectorState = new VectorDrawableState(); 2156c319ca1275c8db892c39b48fc54864c949f9171Romain Guy } 216f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 217f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy private VectorDrawable(@NonNull VectorDrawableState state) { 218f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mVectorState = state; 219f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 220bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } 2217ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 222bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy @Override 223bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy public Drawable mutate() { 224bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy if (!mMutated && super.mutate() == this) { 2258aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy mVectorState = new VectorDrawableState(mVectorState); 226bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mMutated = true; 227bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } 228bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return this; 2292542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy } 2302542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy 2317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy /** 232bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * @hide 233bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy */ 234bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy public void clearMutated() { 2358fb954263dd2f918ad339045cc6d82e346515599Romain Guy super.clearMutated(); 236bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mMutated = false; 2378fb954263dd2f918ad339045cc6d82e346515599Romain Guy } 2382542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy 2397ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy Object getTargetByName(String name) { 240bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return mVectorState.mVPathRenderer.mVGTargetsMap.get(name); 241bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } 2428aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy 2438aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy @Override 2448fb954263dd2f918ad339045cc6d82e346515599Romain Guy public ConstantState getConstantState() { 245bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy mVectorState.mChangingConfigurations = getChangingConfigurations(); 246bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy return mVectorState; 247bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy } 2487ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy 249bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy @Override 250eb99356a0548684a501766e6a524529ab93304c8Romain Guy public void draw(Canvas canvas) { 251bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy final Rect bounds = getBounds(); 252bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy if (bounds.width() <= 0 || bounds.height() <= 0) { 2537ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy // Nothing to draw 254bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy return; 255eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 256eb99356a0548684a501766e6a524529ab93304c8Romain Guy 257eb99356a0548684a501766e6a524529ab93304c8Romain Guy final int saveCount = canvas.save(); 258eb99356a0548684a501766e6a524529ab93304c8Romain Guy final boolean needMirroring = needMirroring(); 259eb99356a0548684a501766e6a524529ab93304c8Romain Guy 260eb99356a0548684a501766e6a524529ab93304c8Romain Guy canvas.translate(bounds.left, bounds.top); 2618b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy if (needMirroring) { 2628b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy canvas.translate(bounds.width(), 0); 2638b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy canvas.scale(-1.0f, 1.0f); 2642542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy } 265746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy 2668fb954263dd2f918ad339045cc6d82e346515599Romain Guy // Color filters always override tint filters. 2672542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy final ColorFilter colorFilter = mColorFilter == null ? mTintFilter : mColorFilter; 2685ec9924d24495822b589f1a17996655d66273b30Romain Guy 2695ec9924d24495822b589f1a17996655d66273b30Romain Guy if (!mAllowCaching) { 2705ec9924d24495822b589f1a17996655d66273b30Romain Guy // AnimatedVectorDrawable 2715ec9924d24495822b589f1a17996655d66273b30Romain Guy if (!mVectorState.hasTranslucentRoot()) { 2722542d199745cdf3ec910b8e3e4cff5851ed24e9bRomain Guy mVectorState.mVPathRenderer.draw( 273d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy canvas, bounds.width(), bounds.height(), colorFilter); 2745cbbce535744b89df5ecea95de21ee3733298260Romain Guy } else { 275f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mVectorState.createCachedBitmapIfNeeded(bounds); 276bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mVectorState.updateCachedBitmap(bounds); 277bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter); 278bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 279bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } else { 2805c13d89c1332fcc499379b9064b891187b75ca32Chet Haase // Static Vector Drawable case. 281eb99356a0548684a501766e6a524529ab93304c8Romain Guy mVectorState.createCachedBitmapIfNeeded(bounds); 282eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (!mVectorState.canReuseCache()) { 283d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy mVectorState.updateCachedBitmap(bounds); 284af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy mVectorState.updateCacheStates(); 285e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy } 286e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter); 287e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy } 288e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy 289e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy canvas.restoreToCount(saveCount); 290e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy } 291e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy 292e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy @Override 293e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy public int getAlpha() { 294e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy return mVectorState.mVPathRenderer.getRootAlpha(); 295e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy } 296e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy 297e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy @Override 298a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy public void setAlpha(int alpha) { 299a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) { 300e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy mVectorState.mVPathRenderer.setRootAlpha(alpha); 301d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy invalidateSelf(); 302d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 303dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy } 304dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy 305d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy @Override 306d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy public void setColorFilter(ColorFilter colorFilter) { 307bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mColorFilter = colorFilter; 308bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy invalidateSelf(); 309bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 310bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy 3115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @Override 3128aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy public void setTintList(ColorStateList tint) { 3138b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy final VectorDrawableState state = mVectorState; 3148aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy if (state.mTint != tint) { 3158aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy state.mTint = tint; 3168aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode); 3178b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy invalidateSelf(); 318d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } 319bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 3201c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3211c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3221c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public void setTintMode(Mode tintMode) { 3231c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy final VectorDrawableState state = mVectorState; 3241c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy if (state.mTintMode != tintMode) { 3251c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy state.mTintMode = tintMode; 3261c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode); 3271c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy invalidateSelf(); 3281c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3291c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3301c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3311c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3321c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public boolean isStateful() { 3331c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy return super.isStateful() || (mVectorState != null && mVectorState.mTint != null 3341c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy && mVectorState.mTint.isStateful()); 3351c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3361c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3376b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy @Override 3386b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy protected boolean onStateChange(int[] stateSet) { 3396b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy final VectorDrawableState state = mVectorState; 3406b7bd24659fb175fe1f0e97c86c18969918b496aRomain Guy if (state.mTint != null && state.mTintMode != null) { 3411c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 3421c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy invalidateSelf(); 3431c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy return true; 3441c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 34587a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy return false; 3461c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3471c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3481c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3491c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public int getOpacity() { 3501c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy return PixelFormat.TRANSLUCENT; 3511c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3521c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3531c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3541c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public int getIntrinsicWidth() { 3551c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy return (int) mVectorState.mVPathRenderer.mBaseWidth; 3561c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3571c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3581c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3591c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public int getIntrinsicHeight() { 3601c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy return (int) mVectorState.mVPathRenderer.mBaseHeight; 3611c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy } 3621c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 3631c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy @Override 3641c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy public boolean canApplyTheme() { 36587a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme(); 36687a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy } 36787a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy 36887a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy @Override 36987a76578f76f4a6bceb187da6b7a01899ca0d85aRomain Guy public void applyTheme(Theme t) { 3701c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy super.applyTheme(t); 371d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy 372eb99356a0548684a501766e6a524529ab93304c8Romain Guy final VectorDrawableState state = mVectorState; 373eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (state == null) { 374eb99356a0548684a501766e6a524529ab93304c8Romain Guy return; 375fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 376dda570201ac851dd85af3861f7e575721d3345daRomain Guy 377eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (state.mThemeAttrs != null) { 378eb99356a0548684a501766e6a524529ab93304c8Romain Guy final TypedArray a = t.resolveAttributes( 379f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy state.mThemeAttrs, R.styleable.VectorDrawable); 3808aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy try { 381ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy state.mCacheDirty = true; 382ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy updateStateFromTypedArray(a); 383ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy } catch (XmlPullParserException e) { 384ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy throw new RuntimeException(e); 385eb99356a0548684a501766e6a524529ab93304c8Romain Guy } finally { 386ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy a.recycle(); 387eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 38858ae6db4ff8a9d0910e1183ee8be9a038a2712a6Romain Guy } 389ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy 390ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy // Apply theme to contained color state list. 391ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy if (state.mTint != null && state.mTint.canApplyTheme()) { 392ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy state.mTint.applyTheme(t); 393ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy } 394ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy 395ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy final VPathRenderer path = state.mVPathRenderer; 396ae517591d96be39f5f18a1716c856ade13a8bcc7Romain Guy if (path != null && path.canApplyTheme()) { 397eb99356a0548684a501766e6a524529ab93304c8Romain Guy path.applyTheme(t); 398bf434114cbf55b216fdc76fc8d65a75e84c9dab5Romain Guy } 399746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy 400746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy // Update local state. 40132963c393a804db2cd86c24443c2f1c6eee6064bRomain Guy mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 402dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy } 403e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy 404dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy /** 405dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. 406dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy * This is used to calculate the path animation accuracy. 407af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy * 408b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy * @hide 409b025b9c8b4efefadb01937db61a1f8ee7d2452bfRomain Guy */ 410dda570201ac851dd85af3861f7e575721d3345daRomain Guy public float getPixelSize() { 4115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mVectorState == null || mVectorState.mVPathRenderer == null || 4128550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy mVectorState.mVPathRenderer.mBaseWidth == 0 || 413f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy mVectorState.mVPathRenderer.mBaseHeight == 0 || 414f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy mVectorState.mVPathRenderer.mViewportHeight == 0 || 415bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mVectorState.mVPathRenderer.mViewportWidth == 0) { 416bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy return 1; // fall back to 1:1 pixel mapping. 417dda570201ac851dd85af3861f7e575721d3345daRomain Guy } 418f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth; 4198aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight; 4208550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth; 4218550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight; 422171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy float scaleX = viewportWidth / intrinsicWidth; 423dda570201ac851dd85af3861f7e575721d3345daRomain Guy float scaleY = viewportHeight / intrinsicHeight; 4248fb954263dd2f918ad339045cc6d82e346515599Romain Guy return Math.min(scaleX, scaleY); 4258fb954263dd2f918ad339045cc6d82e346515599Romain Guy } 426dda570201ac851dd85af3861f7e575721d3345daRomain Guy 4271d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy /** @hide */ 428eb99356a0548684a501766e6a524529ab93304c8Romain Guy public static VectorDrawable create(Resources resources, int rid) { 4295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy try { 430eb99356a0548684a501766e6a524529ab93304c8Romain Guy final XmlPullParser parser = resources.getXml(rid); 431eb99356a0548684a501766e6a524529ab93304c8Romain Guy final AttributeSet attrs = Xml.asAttributeSet(parser); 432eb99356a0548684a501766e6a524529ab93304c8Romain Guy int type; 433514fb18827186591d66973c2362c859b64b63556Romain Guy while ((type=parser.next()) != XmlPullParser.START_TAG && 434514fb18827186591d66973c2362c859b64b63556Romain Guy type != XmlPullParser.END_DOCUMENT) { 435514fb18827186591d66973c2362c859b64b63556Romain Guy // Empty loop 436514fb18827186591d66973c2362c859b64b63556Romain Guy } 437514fb18827186591d66973c2362c859b64b63556Romain Guy if (type != XmlPullParser.START_TAG) { 438514fb18827186591d66973c2362c859b64b63556Romain Guy throw new XmlPullParserException("No start tag found"); 439514fb18827186591d66973c2362c859b64b63556Romain Guy } 440514fb18827186591d66973c2362c859b64b63556Romain Guy 441514fb18827186591d66973c2362c859b64b63556Romain Guy final VectorDrawable drawable = new VectorDrawable(); 442514fb18827186591d66973c2362c859b64b63556Romain Guy drawable.inflate(resources, parser, attrs); 443514fb18827186591d66973c2362c859b64b63556Romain Guy 444ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy return drawable; 445eb99356a0548684a501766e6a524529ab93304c8Romain Guy } catch (XmlPullParserException e) { 446f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy Log.e(LOGTAG, "parser error", e); 447d55a86120dd1e8ebcc6906c9ffd463f7460348daRomain Guy } catch (IOException e) { 448bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy Log.e(LOGTAG, "parser error", e); 449bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy } 4505b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return null; 4515b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 4525b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4535b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy private static int applyAlpha(int color, float alpha) { 4545b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int alphaBytes = Color.alpha(color); 4555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy color &= 0x00FFFFFF; 4565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy color |= ((int) (alphaBytes * alpha)) << 24; 4575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return color; 4585b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 4595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4605b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @Override 4615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme) 4625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throws XmlPullParserException, IOException { 4635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final VectorDrawableState state = mVectorState; 4645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final VPathRenderer pathRenderer = new VPathRenderer(); 4655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mVPathRenderer = pathRenderer; 4665b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4675b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable); 4685b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy updateStateFromTypedArray(a); 4695b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy a.recycle(); 4705b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4715ec9924d24495822b589f1a17996655d66273b30Romain Guy state.mCacheDirty = true; 4725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy inflateInternal(res, parser, attrs, theme); 4735b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode); 4755b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 4765b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException { 4785b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final VectorDrawableState state = mVectorState; 4795b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final VPathRenderer pathRenderer = state.mVPathRenderer; 4805b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4815b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Account for any configuration changes. 4825b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mChangingConfigurations |= a.getChangingConfigurations(); 4835b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4845b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Extract the theme attributes, if any. 4855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mThemeAttrs = a.extractThemeAttrs(); 4865b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4875b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1); 4885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (tintMode != -1) { 4895b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN); 4905b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 4915b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint); 4935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (tint != null) { 4945b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mTint = tint; 4955b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 4965b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 4975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy state.mAutoMirrored = a.getBoolean( 4985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored); 4995b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5005b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy pathRenderer.mViewportWidth = a.getFloat( 5015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy R.styleable.VectorDrawable_viewportWidth, pathRenderer.mViewportWidth); 5025b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy pathRenderer.mViewportHeight = a.getFloat( 5035b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy R.styleable.VectorDrawable_viewportHeight, pathRenderer.mViewportHeight); 5045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (pathRenderer.mViewportWidth <= 0) { 5065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throw new XmlPullParserException(a.getPositionDescription() + 5075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy "<vector> tag requires viewportWidth > 0"); 5085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } else if (pathRenderer.mViewportHeight <= 0) { 5095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throw new XmlPullParserException(a.getPositionDescription() + 5105b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy "<vector> tag requires viewportHeight > 0"); 5115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5135b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy pathRenderer.mBaseWidth = a.getDimension( 5145b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy R.styleable.VectorDrawable_width, pathRenderer.mBaseWidth); 5155b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy pathRenderer.mBaseHeight = a.getDimension( 5165b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy R.styleable.VectorDrawable_height, pathRenderer.mBaseHeight); 5175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (pathRenderer.mBaseWidth <= 0) { 5195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throw new XmlPullParserException(a.getPositionDescription() + 5205b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy "<vector> tag requires width > 0"); 5215b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } else if (pathRenderer.mBaseHeight <= 0) { 5225b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throw new XmlPullParserException(a.getPositionDescription() + 5235b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy "<vector> tag requires height > 0"); 5245b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5255b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5261c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy final float alphaInFloat = a.getFloat(R.styleable.VectorDrawable_alpha, 5271c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy pathRenderer.getAlpha()); 5281c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy pathRenderer.setAlpha(alphaInFloat); 5291d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 5301d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy final String name = a.getString(R.styleable.VectorDrawable_name); 5311d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy if (name != null) { 5321d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy pathRenderer.mRootName = name; 5331d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy pathRenderer.mVGTargetsMap.put(name, pathRenderer); 5341d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy } 5355b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 536eb99356a0548684a501766e6a524529ab93304c8Romain Guy 537eb99356a0548684a501766e6a524529ab93304c8Romain Guy private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs, 538eb99356a0548684a501766e6a524529ab93304c8Romain Guy Theme theme) throws XmlPullParserException, IOException { 539eb99356a0548684a501766e6a524529ab93304c8Romain Guy final VectorDrawableState state = mVectorState; 540eb99356a0548684a501766e6a524529ab93304c8Romain Guy final VPathRenderer pathRenderer = state.mVPathRenderer; 541eb99356a0548684a501766e6a524529ab93304c8Romain Guy boolean noPathTag = true; 5421d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 5431d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy // Use a stack to help to build the group tree. 5441d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy // The top of the stack is always the current group. 545eb99356a0548684a501766e6a524529ab93304c8Romain Guy final Stack<VGroup> groupStack = new Stack<VGroup>(); 546f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy groupStack.push(pathRenderer.mRootGroup); 5471c740bce8a762f02b5283045a0e2de7c8fb41277Romain Guy 5485b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int eventType = parser.getEventType(); 5495b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy while (eventType != XmlPullParser.END_DOCUMENT) { 550f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy if (eventType == XmlPullParser.START_TAG) { 551f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy final String tagName = parser.getName(); 55203750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy final VGroup currentGroup = groupStack.peek(); 5538b55f377655d13a445b08a0a8ed09b6e95c752b0Romain Guy 554746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy if (SHAPE_PATH.equals(tagName)) { 5555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final VFullPath path = new VFullPath(); 5565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy path.inflate(res, attrs, theme); 5575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy currentGroup.mChildren.add(path); 558eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (path.getPathName() != null) { 5595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 560171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy } 561171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy noPathTag = false; 562171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy state.mChangingConfigurations |= path.mChangingConfigurations; 5635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } else if (SHAPE_CLIP_PATH.equals(tagName)) { 564171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy final VClipPath path = new VClipPath(); 565171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy path.inflate(res, attrs, theme); 566171c592f0b7066acf279863c8a52ddabea49d3dbRomain Guy currentGroup.mChildren.add(path); 567eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (path.getPathName() != null) { 568514fb18827186591d66973c2362c859b64b63556Romain Guy pathRenderer.mVGTargetsMap.put(path.getPathName(), path); 569514fb18827186591d66973c2362c859b64b63556Romain Guy } 570514fb18827186591d66973c2362c859b64b63556Romain Guy state.mChangingConfigurations |= path.mChangingConfigurations; 571514fb18827186591d66973c2362c859b64b63556Romain Guy } else if (SHAPE_GROUP.equals(tagName)) { 572eb99356a0548684a501766e6a524529ab93304c8Romain Guy VGroup newChildGroup = new VGroup(); 5731d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy newChildGroup.inflate(res, attrs, theme); 574eb99356a0548684a501766e6a524529ab93304c8Romain Guy currentGroup.mChildren.add(newChildGroup); 575eb99356a0548684a501766e6a524529ab93304c8Romain Guy groupStack.push(newChildGroup); 576eb99356a0548684a501766e6a524529ab93304c8Romain Guy if (newChildGroup.getGroupName() != null) { 577eb99356a0548684a501766e6a524529ab93304c8Romain Guy pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(), 578eb99356a0548684a501766e6a524529ab93304c8Romain Guy newChildGroup); 579eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 580eb99356a0548684a501766e6a524529ab93304c8Romain Guy state.mChangingConfigurations |= newChildGroup.mChangingConfigurations; 581eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 582eb99356a0548684a501766e6a524529ab93304c8Romain Guy } else if (eventType == XmlPullParser.END_TAG) { 583eb99356a0548684a501766e6a524529ab93304c8Romain Guy final String tagName = parser.getName(); 584746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy if (SHAPE_GROUP.equals(tagName)) { 585746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy groupStack.pop(); 586eb99356a0548684a501766e6a524529ab93304c8Romain Guy } 5878550c4c7b5952b7a4e1e0ede95c9492d03099a13Romain Guy } 5881d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy eventType = parser.next(); 5891d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy } 5901d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy 5911d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy // Print the tree out for debug. 5921d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy if (DBG_VECTOR_DRAWABLE) { 5931d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy printGroupTree(pathRenderer.mRootGroup, 0); 5945b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 5955b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5965b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (noPathTag) { 5975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final StringBuffer tag = new StringBuffer(); 5985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 5995b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (tag.length() > 0) { 6005b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy tag.append(" or "); 6015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6025b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy tag.append(SHAPE_PATH); 6035b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy throw new XmlPullParserException("no " + tag + " defined"); 6055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy private void printGroupTree(VGroup currentGroup, int level) { 6095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy String indent = ""; 6105b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy for (int i = 0; i < level; i++) { 6115b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy indent += " "; 6125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6135b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Print the current node 6145b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName() 6155b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy + " rotation is " + currentGroup.mRotate); 6165b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString()); 6175b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Then print all the children groups 6185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy for (int i = 0; i < currentGroup.mChildren.size(); i++) { 6195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Object child = currentGroup.mChildren.get(i); 620f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy if (child instanceof VGroup) { 6215b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy printGroupTree((VGroup) child, level + 1); 6225b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6235b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6245b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6257230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 6267230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy @Override 6277230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public int getChangingConfigurations() { 628ada830f639591b99c3e40de22b07296c7932a33fRomain Guy return super.getChangingConfigurations() | mVectorState.mChangingConfigurations; 6297230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 6307230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 6317230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy void setAllowCaching(boolean allowCaching) { 6327230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy mAllowCaching = allowCaching; 633ada830f639591b99c3e40de22b07296c7932a33fRomain Guy } 6347230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 635c038ea358aadca082198f3effc550d33135bf426Romain Guy private boolean needMirroring() { 6367230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL; 6375b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6385b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6395b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @Override 6405b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public void setAutoMirrored(boolean mirrored) { 6415b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mVectorState.mAutoMirrored != mirrored) { 642f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy mVectorState.mAutoMirrored = mirrored; 6435b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy invalidateSelf(); 644f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy } 6455b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6465b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6475b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @Override 6485b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public boolean isAutoMirrored() { 6495b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mVectorState.mAutoMirrored; 6505b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6515b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6525b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy private static class VectorDrawableState extends ConstantState { 6535b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int[] mThemeAttrs; 6545b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int mChangingConfigurations; 6555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy VPathRenderer mVPathRenderer; 6565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy ColorStateList mTint = null; 6575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Mode mTintMode = DEFAULT_TINT_MODE; 6585b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy boolean mAutoMirrored; 6595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6605b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Bitmap mCachedBitmap; 6615b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int[] mCachedThemeAttrs; 6625b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy ColorStateList mCachedTint; 6635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Mode mCachedTintMode; 6645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy int mCachedRootAlpha; 6655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy boolean mCachedAutoMirrored; 6667230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy boolean mCacheDirty; 6675b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6685b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy /** Temporary paint object used to draw cached bitmaps. */ 6695b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Paint mTempPaint; 6705b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6715b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // Deep copy for mutate() or implicitly mutate. 6725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public VectorDrawableState(VectorDrawableState copy) { 6735b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (copy != null) { 6745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mThemeAttrs = copy.mThemeAttrs; 6755b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mChangingConfigurations = copy.mChangingConfigurations; 6765b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mVPathRenderer = new VPathRenderer(copy.mVPathRenderer); 6775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (copy.mVPathRenderer.mFillPaint != null) { 6785b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint); 6795b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6805b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (copy.mVPathRenderer.mStrokePaint != null) { 6815b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint); 6825b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6835b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTint = copy.mTint; 6845b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTintMode = copy.mTintMode; 6855b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mAutoMirrored = copy.mAutoMirrored; 6865b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6875b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6895b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter) { 6905b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy // The bitmap's size is the same as the bounds. 6915b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final Paint p = getPaint(filter); 6925b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy canvas.drawBitmap(mCachedBitmap, 0, 0, p); 6935b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6945b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6955b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public boolean hasTranslucentRoot() { 6965b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mVPathRenderer.getRootAlpha() < 255; 6975b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 6985b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 6995b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy /** 700f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy * @return null when there is no need for alpha paint. 7015b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy */ 7025b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public Paint getPaint(ColorFilter filter) { 703f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy if (!hasTranslucentRoot() && filter == null) { 7045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return null; 7055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 7065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 7075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (mTempPaint == null) { 7085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTempPaint = new Paint(); 7095b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTempPaint.setFilterBitmap(true); 7105b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 711f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy mTempPaint.setAlpha(mVPathRenderer.getRootAlpha()); 7125b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTempPaint.setColorFilter(filter); 713f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy return mTempPaint; 7141bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy } 7151bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy 7161bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy public void updateCachedBitmap(Rect bounds) { 7171bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy mCachedBitmap.eraseColor(Color.TRANSPARENT); 7181bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy Canvas tmpCanvas = new Canvas(mCachedBitmap); 7191bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height(), null); 7201bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy } 7211bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy 7221bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy public void createCachedBitmapIfNeeded(Rect bounds) { 7231bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy if (mCachedBitmap == null || !canReuseBitmap(bounds.width(), 7241bd1bad0b4a75e633c5edbe802bf6fb4dd765161Romain Guy bounds.height())) { 7255b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mCachedBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), 7265b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Bitmap.Config.ARGB_8888); 7275b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mCacheDirty = true; 7285b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 7295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 7308694230ff25fa0a60e480d424843e56b718f0516Romain Guy } 731af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy 7328694230ff25fa0a60e480d424843e56b718f0516Romain Guy public boolean canReuseBitmap(int width, int height) { 7335b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (width == mCachedBitmap.getWidth() 7345b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && height == mCachedBitmap.getHeight()) { 7355b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return true; 7368694230ff25fa0a60e480d424843e56b718f0516Romain Guy } 7378694230ff25fa0a60e480d424843e56b718f0516Romain Guy return false; 7385b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 7395b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 7405b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public boolean canReuseCache() { 7415b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy if (!mCacheDirty 7425b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && mCachedThemeAttrs == mThemeAttrs 7435b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && mCachedTint == mTint 7445b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && mCachedTintMode == mTintMode 7455b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && mCachedAutoMirrored == mAutoMirrored 7465b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) { 7475b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return true; 7488694230ff25fa0a60e480d424843e56b718f0516Romain Guy } 7498694230ff25fa0a60e480d424843e56b718f0516Romain Guy return false; 7508694230ff25fa0a60e480d424843e56b718f0516Romain Guy } 7518694230ff25fa0a60e480d424843e56b718f0516Romain Guy 7525b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public void updateCacheStates() { 7538694230ff25fa0a60e480d424843e56b718f0516Romain Guy // Use shallow copy here and shallow comparison in canReuseCache(), 7548694230ff25fa0a60e480d424843e56b718f0516Romain Guy // likely hit cache miss more, but practically not much difference. 755bd6b79b40247aea7bfe13d0831c6c0472df6c636Romain Guy mCachedThemeAttrs = mThemeAttrs; 756f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mCachedTint = mTint; 757f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mCachedTintMode = mTintMode; 758f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mCachedRootAlpha = mVPathRenderer.getRootAlpha(); 759f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy mCachedAutoMirrored = mAutoMirrored; 7608aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy mCacheDirty = false; 761f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 762f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 763f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy @Override 7648aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy public boolean canApplyTheme() { 765f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return mThemeAttrs != null 766f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy || (mVPathRenderer != null && mVPathRenderer.canApplyTheme()) 767f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy || (mTint != null && mTint.canApplyTheme()) 7688aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy || super.canApplyTheme(); 769f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 770f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 771807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy public VectorDrawableState() { 772807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy mVPathRenderer = new VPathRenderer(); 773807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy } 774807daf7df615b60ce6fc41355aabe3aa353cebabRomain Guy 775f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy @Override 7768aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy public Drawable newDrawable() { 777f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy return new VectorDrawable(this); 778f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 77941030da16856c8869e1e51d4a0405432fa96614eRomain Guy 78099bcdc52dcb365ed7d8cfa13540fb33fbcbbac9dRomain Guy @Override 78199bcdc52dcb365ed7d8cfa13540fb33fbcbbac9dRomain Guy public Drawable newDrawable(Resources res) { 78299bcdc52dcb365ed7d8cfa13540fb33fbcbbac9dRomain Guy return new VectorDrawable(this); 78399bcdc52dcb365ed7d8cfa13540fb33fbcbbac9dRomain Guy } 78441030da16856c8869e1e51d4a0405432fa96614eRomain Guy 78541030da16856c8869e1e51d4a0405432fa96614eRomain Guy @Override 786f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy public int getChangingConfigurations() { 7878aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy return mChangingConfigurations; 788f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 789f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 790f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 791e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy private static class VPathRenderer { 792e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy /* Right now the internal data structure is organized as a tree. 793e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy * Each node can be a group node, or a path. 794e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy * A group node can have groups or paths as children, but a path node has 795f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * no children. 796f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * One example can be: 797f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * Root Group 798f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * / | \ 799f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * Group Path Group 800f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy * / \ | 801bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * Path Path Path 802e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy * 803e5ebcb0107a939395e03592fd44c746cd09e311dRomain Guy */ 804eb99356a0548684a501766e6a524529ab93304c8Romain Guy // Variables that only used temporarily inside the draw() call, so there 805746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy // is no need for deep copying. 8069d5316e3f56d138504565ff311145ac01621dff4Romain Guy private final Path mPath; 8079d5316e3f56d138504565ff311145ac01621dff4Romain Guy private final Path mRenderPath; 8089d5316e3f56d138504565ff311145ac01621dff4Romain Guy private final Matrix mFinalPathMatrix = new Matrix(); 809079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy 810bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy private Paint mStrokePaint; 811bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy private Paint mFillPaint; 812c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy private PathMeasure mPathMeasure; 813af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy 814dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy ///////////////////////////////////////////////////// 815dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy // Variables below need to be copied (deep copy if applicable) for mutation. 816dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy private int mChangingConfigurations; 8171d83e1981c8b89da93dff37a4f8b2b1ad8480b44Romain Guy private final VGroup mRootGroup; 8188aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy float mBaseWidth = 0; 819d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy float mBaseHeight = 0; 820d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy float mViewportWidth = 0; 821d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy float mViewportHeight = 0; 822d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy int mRootAlpha = 0xFF; 823d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy String mRootName = null; 824d2a1ff003b9b1212c9ab4b5f679b5b097720a359Romain Guy 825c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>(); 826c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy 827079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy public VPathRenderer() { 828079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy mRootGroup = new VGroup(); 8297ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy mPath = new Path(); 830746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy mRenderPath = new Path(); 8317ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy } 8328aef54fa17f2a3753d9a8f2027629bc480088f69Romain Guy 833e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy public void setRootAlpha(int alpha) { 834e4d011201cea40d46cb2b2eef401db8fddc5c9c6Romain Guy mRootAlpha = alpha; 835f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 83670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 83770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public int getRootAlpha() { 83870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy return mRootAlpha; 83970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 84070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 84170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // setAlpha() and getAlpha() are used mostly for animation purpose, since 84270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Animator like to use alpha from 0 to 1. 84370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public void setAlpha(float alpha) { 84470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy setRootAlpha((int) (alpha * 255)); 84570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 84670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 84770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy @SuppressWarnings("unused") 84870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public float getAlpha() { 84970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy return getRootAlpha() / 255.0f; 8508d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 85170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 85270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public VPathRenderer(VPathRenderer copy) { 85370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap); 85470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mPath = new Path(copy.mPath); 85570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mRenderPath = new Path(copy.mRenderPath); 85670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mBaseWidth = copy.mBaseWidth; 85770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mBaseHeight = copy.mBaseHeight; 85870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mViewportWidth = copy.mViewportWidth; 8598d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mViewportHeight = copy.mViewportHeight; 8608d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mChangingConfigurations = copy.mChangingConfigurations; 8618d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mRootAlpha = copy.mRootAlpha; 8628d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mRootName = copy.mRootName; 8638d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy if (copy.mRootName != null) { 86470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mVGTargetsMap.put(copy.mRootName, this); 865fa7952dbb86a8aff0c90418aa77dddee3802c23aRomain Guy } 866fa7952dbb86a8aff0c90418aa77dddee3802c23aRomain Guy } 867fa7952dbb86a8aff0c90418aa77dddee3802c23aRomain Guy 86870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public boolean canApplyTheme() { 86970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // If one of the paths can apply theme, then return true; 87070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy return recursiveCanApplyTheme(mRootGroup); 87170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 87286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 87386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy private boolean recursiveCanApplyTheme(VGroup currentGroup) { 87486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy // We can do a tree traverse here, if there is one path return true, 87586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy // then we return true for the whole tree. 87686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy final ArrayList<Object> children = currentGroup.mChildren; 87786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 87886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy for (int i = 0; i < children.size(); i++) { 87986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy Object child = children.get(i); 88086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy if (child instanceof VGroup) { 88186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy VGroup childGroup = (VGroup) child; 88270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (childGroup.canApplyTheme() 88370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy || recursiveCanApplyTheme(childGroup)) { 88470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy return true; 88570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 88670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else if (child instanceof VPath) { 88770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VPath childPath = (VPath) child; 88870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (childPath.canApplyTheme()) { 88970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy return true; 89070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 89186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 89286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 89386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return false; 89486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 89586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 89686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy public void applyTheme(Theme t) { 89786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy // Apply theme to every path of the tree. 89886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy recursiveApplyTheme(mRootGroup, t); 89986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 90070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 90170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy private void recursiveApplyTheme(VGroup currentGroup, Theme t) { 90270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // We can do a tree traverse here, apply theme to all paths which 90370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // can apply theme. 90470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy final ArrayList<Object> children = currentGroup.mChildren; 90570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy for (int i = 0; i < children.size(); i++) { 90670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy Object child = children.get(i); 90770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (child instanceof VGroup) { 90870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VGroup childGroup = (VGroup) child; 90970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (childGroup.canApplyTheme()) { 91070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy childGroup.applyTheme(t); 91170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 91270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy recursiveApplyTheme(childGroup, t); 91370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else if (child instanceof VPath) { 91470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VPath childPath = (VPath) child; 91570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (childPath.canApplyTheme()) { 91670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy childPath.applyTheme(t); 91770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 91870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 91970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 92070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 92170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 92270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix, 92370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy Canvas canvas, int w, int h, ColorFilter filter) { 92470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Calculate current group's matrix by preConcat the parent's and 92570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // and the current one on the top of the stack. 92670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Basically the Mfinal = Mviewport * M0 * M1 * M2; 92770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Mi the local matrix at level i of the group tree. 92870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy currentGroup.mStackedMatrix.set(currentMatrix); 92970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix); 93070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 93170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Save the current clip information, which is local to this group. 93270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy canvas.save(); 93370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Draw the group tree in the same order as the XML file. 93470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy for (int i = 0; i < currentGroup.mChildren.size(); i++) { 93570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy Object child = currentGroup.mChildren.get(i); 93670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (child instanceof VGroup) { 93770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VGroup childGroup = (VGroup) child; 93870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy drawGroupTree(childGroup, currentGroup.mStackedMatrix, 93970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy canvas, w, h, filter); 94070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else if (child instanceof VPath) { 94170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VPath childPath = (VPath) child; 9428d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy drawPath(currentGroup, childPath, canvas, w, h, filter); 9438d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 9448d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 9458d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy canvas.restore(); 94670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 94770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 94870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy public void draw(Canvas canvas, int w, int h, ColorFilter filter) { 94970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy // Travese the tree in pre-order to draw. 95070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvas, w, h, filter); 95170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 95270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 95370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h, 95486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy ColorFilter filter) { 95586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy final float scaleX = w / mViewportWidth; 95686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy final float scaleY = h / mViewportHeight; 95786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy final float minScale = Math.min(scaleX, scaleY); 95886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 95986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mFinalPathMatrix.set(vGroup.mStackedMatrix); 96086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mFinalPathMatrix.postScale(scaleX, scaleY); 96186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 96286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy vPath.toPath(mPath); 96386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy final Path path = mPath; 96470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 96570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mRenderPath.reset(); 96670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 9675536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy if (vPath.isClipPath()) { 96870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mRenderPath.addPath(path, mFinalPathMatrix); 96970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy canvas.clipPath(mRenderPath, Region.Op.REPLACE); 97070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } else { 97170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy VFullPath fullPath = (VFullPath) vPath; 97286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) { 9735536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f; 97486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f; 9755536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy 9765536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy if (mPathMeasure == null) { 9775536841e5452172e7772d84ad5f4a2fc7059c9ddRomain Guy mPathMeasure = new PathMeasure(); 97870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 97970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mPathMeasure.setPath(mPath, false); 98070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 98170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy float len = mPathMeasure.getLength(); 98270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy start = start * len; 98370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy end = end * len; 98470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy path.reset(); 98570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (start > end) { 98670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mPathMeasure.getSegment(start, len, path, true); 9878d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mPathMeasure.getSegment(0f, end, path, true); 9888d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } else { 9898d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mPathMeasure.getSegment(start, end, path, true); 9908d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 9918d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy path.rLineTo(0, 0); // fix bug in measure 9928d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 99370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mRenderPath.addPath(path, mFinalPathMatrix); 99470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 99570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (fullPath.mFillColor != Color.TRANSPARENT) { 99670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (mFillPaint == null) { 99770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mFillPaint = new Paint(); 99870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mFillPaint.setStyle(Paint.Style.FILL); 99970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mFillPaint.setAntiAlias(true); 100070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 100170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 100270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy final Paint fillPaint = mFillPaint; 100370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha)); 100470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy fillPaint.setColorFilter(filter); 100570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy canvas.drawPath(mRenderPath, fillPaint); 100670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 100770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 100870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (fullPath.mStrokeColor != Color.TRANSPARENT) { 100970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (mStrokePaint == null) { 101070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mStrokePaint = new Paint(); 101170ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mStrokePaint.setStyle(Paint.Style.STROKE); 101270ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy mStrokePaint.setAntiAlias(true); 101370ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 101470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 101570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy final Paint strokePaint = mStrokePaint; 101670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (fullPath.mStrokeLineJoin != null) { 101770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin); 101870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 101970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy 102070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy if (fullPath.mStrokeLineCap != null) { 10218d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy strokePaint.setStrokeCap(fullPath.mStrokeLineCap); 10228d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 10238d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy 102470ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit); 102570ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha)); 102670ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy strokePaint.setColorFilter(filter); 102770ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy strokePaint.setStrokeWidth(fullPath.mStrokeWidth * minScale); 102870ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy canvas.drawPath(mRenderPath, strokePaint); 102970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 103070ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy } 1031f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 1032f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy } 1033f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy 1034ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy private static class VGroup { 10350fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy // mStackedMatrix is only used temporarily when drawing, it combines all 10360fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy // the parents' local matrices with the current one. 10370fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy private final Matrix mStackedMatrix = new Matrix(); 1038ffac7fc5042296a459d0f5a450dbfe20917093dcRomain Guy 10390fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy ///////////////////////////////////////////////////// 10400fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy // Variables below need to be copied (deep copy if applicable) for mutation. 10410fe478ea04720a57ef3919dbc23711bc7eba517fRomain Guy final ArrayList<Object> mChildren = new ArrayList<Object>(); 10425c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 10436926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mRotate = 0; 10446926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mPivotX = 0; 10456926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mPivotY = 0; 10466926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mScaleX = 1; 10476926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mScaleY = 1; 10486926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mTranslateX = 0; 10496926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private float mTranslateY = 0; 105086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 10518164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy // mLocalMatrix is updated based on the update of transformation information, 10529cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy // either parsed from the XML or by animation. 105322158e139a3d6c6a9787ca0de224e9368f643284Romain Guy private final Matrix mLocalMatrix = new Matrix(); 105422158e139a3d6c6a9787ca0de224e9368f643284Romain Guy private int mChangingConfigurations; 10556926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy private int[] mThemeAttrs; 10568ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy private String mGroupName = null; 10578ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 10585c13d89c1332fcc499379b9064b891187b75ca32Chet Haase public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) { 1059f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mRotate = copy.mRotate; 1060f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mPivotX = copy.mPivotX; 1061f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mPivotY = copy.mPivotY; 1062f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy mScaleX = copy.mScaleX; 10636926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mScaleY = copy.mScaleY; 10646926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mTranslateX = copy.mTranslateX; 10656926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mTranslateY = copy.mTranslateY; 10666926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mThemeAttrs = copy.mThemeAttrs; 106786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mGroupName = copy.mGroupName; 10688164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy mChangingConfigurations = copy.mChangingConfigurations; 10699cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy if (mGroupName != null) { 107022158e139a3d6c6a9787ca0de224e9368f643284Romain Guy targetsMap.put(mGroupName, this); 107122158e139a3d6c6a9787ca0de224e9368f643284Romain Guy } 10725b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10735b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mLocalMatrix.set(copy.mLocalMatrix); 10745b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 10755b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy final ArrayList<Object> children = copy.mChildren; 10765b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy for (int i = 0; i < children.size(); i++) { 10775b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy Object copyChild = children.get(i); 1078f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy if (copyChild instanceof VGroup) { 1079f86ef57f8bcd8ba43ce222ec6a8b4f67d3600640Romain Guy VGroup copyGroup = (VGroup) copyChild; 10805a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mChildren.add(new VGroup(copyGroup, targetsMap)); 10815a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } else { 10825a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy VPath newPath = null; 10835a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy if (copyChild instanceof VFullPath) { 10845a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy newPath = new VFullPath((VFullPath) copyChild); 10855a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } else if (copyChild instanceof VClipPath) { 10865a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy newPath = new VClipPath((VClipPath) copyChild); 10875a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } else { 10885a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy throw new IllegalStateException("Unknown object in the tree!"); 10895a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 10905a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mChildren.add(newPath); 10915a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy if (newPath.mPathName != null) { 10925a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy targetsMap.put(newPath.mPathName, newPath); 10935a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 10945a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 10955a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 10965a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 10975a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 10985a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy public VGroup() { 10995a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 11005a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11015a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy public String getGroupName() { 11025a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy return mGroupName; 11035a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 11045a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11055a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy public Matrix getLocalMatrix() { 11065a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy return mLocalMatrix; 11075a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 11085a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11095a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy public void inflate(Resources res, AttributeSet attrs, Theme theme) { 11105a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy final TypedArray a = obtainAttributes(res, theme, attrs, 11115a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy R.styleable.VectorDrawableGroup); 11125a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy updateStateFromTypedArray(a); 11135a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy a.recycle(); 11145a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 11155a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11165a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy private void updateStateFromTypedArray(TypedArray a) { 11175a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy // Account for any configuration changes. 11185a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mChangingConfigurations |= a.getChangingConfigurations(); 11195a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11205a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy // Extract the theme attributes, if any. 11215a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mThemeAttrs = a.extractThemeAttrs(); 11225a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11235a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate); 11245a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX); 11255a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY); 11265a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX); 11275a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY); 11285a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX); 11295a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY); 11305a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy 11315a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy final String groupName = a.getString(R.styleable.VectorDrawableGroup_name); 11325a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy if (groupName != null) { 11335a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy mGroupName = groupName; 11345a7b466a2b4b7ced739bd5c31e022de61650545aRomain Guy } 11358ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 11368ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy updateLocalMatrix(); 11378ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy } 11385c13d89c1332fcc499379b9064b891187b75ca32Chet Haase 11396926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy public boolean canApplyTheme() { 11406926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy return mThemeAttrs != null; 11416926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 11426926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 1143746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy public void applyTheme(Theme t) { 11448164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy if (mThemeAttrs == null) { 11459cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy return; 114622158e139a3d6c6a9787ca0de224e9368f643284Romain Guy } 11478164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy 11488ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawableGroup); 11498ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy updateStateFromTypedArray(a); 11508ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy a.recycle(); 1151c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy } 11528ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy 11538ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy private void updateLocalMatrix() { 11548ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy // The order we apply is the same as the 11558ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy // RenderNode.cpp::applyViewPropertyTransforms(). 1156c1396e93b6a5286a5183c00c781b62e940a12c1fRomain Guy mLocalMatrix.reset(); 115703750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy mLocalMatrix.postTranslate(-mPivotX, -mPivotY); 11588ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy mLocalMatrix.postScale(mScaleX, mScaleY); 11598ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy mLocalMatrix.postRotate(mRotate, 0, 0); 116003750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY); 116103750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy } 116203750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy 116303750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 11646620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 11656620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy public float getRotation() { 11666620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy return mRotate; 11676620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 11686620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 11696620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 11706620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy public void setRotation(float rotation) { 11716620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy if (rotation != mRotate) { 11726620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mRotate = rotation; 11736620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy updateLocalMatrix(); 11746620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 11756620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 11766620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 11778ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy @SuppressWarnings("unused") 11788ba548f81d1ab5f1750cbf86098c4a14e0b8beadRomain Guy public float getPivotX() { 1179ce0537b80087a6225273040a987414b1dd081aa0Romain Guy return mPivotX; 1180ce0537b80087a6225273040a987414b1dd081aa0Romain Guy } 11814aa90573bbf86db0d33a3a790c5dbd0d93b95cfeRomain Guy 11824bb942083a0d4db746adf95349108dd8ef842e32Romain Guy @SuppressWarnings("unused") 11835c13d89c1332fcc499379b9064b891187b75ca32Chet Haase public void setPivotX(float pivotX) { 11846926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy if (pivotX != mPivotX) { 11856926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy mPivotX = pivotX; 11866926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy updateLocalMatrix(); 11876926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy } 1188746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy } 11898164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy 11909cccc2b9bdd4850a3f9679569aaec3ab98477a5dRomain Guy @SuppressWarnings("unused") 119122158e139a3d6c6a9787ca0de224e9368f643284Romain Guy public float getPivotY() { 11928164c2d338781c3a3c4a443941070dca5d88f2a7Romain Guy return mPivotY; 1193f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 1194f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy 1195f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy @SuppressWarnings("unused") 1196f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy public void setPivotY(float pivotY) { 1197f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy if (pivotY != mPivotY) { 11982728f961614a385df1f056fc24803a9f65c90fabRomain Guy mPivotY = pivotY; 11994bb942083a0d4db746adf95349108dd8ef842e32Romain Guy updateLocalMatrix(); 1200f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 1201a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy } 12026620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 1203a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy @SuppressWarnings("unused") 12045b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public float getScaleX() { 12055b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mScaleX; 12065b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 12075b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 12085b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @SuppressWarnings("unused") 12098ab4079ca27e36e5c584495bcd71b573598ac021Romain Guy public void setScaleX(float scaleX) { 12106620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy if (scaleX != mScaleX) { 12116620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mScaleX = scaleX; 12126620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy updateLocalMatrix(); 12138ab4079ca27e36e5c584495bcd71b573598ac021Romain Guy } 12146620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 12156620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 12166620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 12176620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy public float getScaleY() { 12186620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy return mScaleY; 12195b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 12205b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 1221a5ef39a21683189e5906c9f252b997f0508e350dRomain Guy @SuppressWarnings("unused") 12225b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy public void setScaleY(float scaleY) { 12236620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy if (scaleY != mScaleY) { 12246620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mScaleY = scaleY; 12256620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy updateLocalMatrix(); 12266620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 12276620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 12286620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 12296620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 12306620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy public float getTranslateX() { 12316620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy return mTranslateX; 12326620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 12336620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 12346620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 12356620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy public void setTranslateX(float translateX) { 12366620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy if (translateX != mTranslateX) { 1237054dc1840941665e32036f9523df51720ad069c8Romain Guy mTranslateX = translateX; 1238f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy updateLocalMatrix(); 1239f7f93556c8fcc640ab5adef79d021a80a72a645aRomain Guy } 12405c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 1241af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy 1242dbc26d2ba13f80a7590c57de2d80530d96832969Romain Guy @SuppressWarnings("unused") 1243a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public float getTranslateY() { 1244a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy return mTranslateY; 1245a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1246a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1247a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy @SuppressWarnings("unused") 1248a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public void setTranslateY(float translateY) { 1249759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy if (translateY != mTranslateY) { 1250759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy mTranslateY = translateY; 1251759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy updateLocalMatrix(); 1252759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy } 1253a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 12547230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 1255a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1256a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy /** 1257a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy * Common Path information for clip path and normal path. 1258a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy */ 1259a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy private static class VPath { 1260a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy protected PathParser.PathDataNode[] mNodes = null; 1261a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy String mPathName; 1262759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy int mChangingConfigurations; 1263a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1264a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public VPath() { 1265759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy // Empty constructor. 12668d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 12678d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy 12688d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy public VPath(VPath copy) { 12698d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mPathName = copy.mPathName; 12708d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mChangingConfigurations = copy.mChangingConfigurations; 12718d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy mNodes = PathParser.deepCopyNodes(copy.mNodes); 12728d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 12738d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy 12748d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy public void toPath(Path path) { 12758d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy path.reset(); 12768d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy if (mNodes != null) { 1277759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy PathParser.PathDataNode.nodesToPath(mNodes, path); 1278a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1279a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1280a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1281a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public String getPathName() { 1282a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy return mPathName; 1283a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1284a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1285a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public boolean canApplyTheme() { 1286a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy return false; 1287a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1288a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1289a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public void applyTheme(Theme t) { 1290a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1291a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1292a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public boolean isClipPath() { 1293a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy return false; 1294a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 1295a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy 1296a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 1297a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy @SuppressWarnings("unused") 1298a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy public PathParser.PathDataNode[] getPathData() { 1299a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy return mNodes; 1300a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 13017230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13027230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy @SuppressWarnings("unused") 13037230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public void setPathData(PathParser.PathDataNode[] nodes) { 13047230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy if (!PathParser.canMorph(mNodes, nodes)) { 13057230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy // This should not happen in the middle of animation. 13067230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy mNodes = PathParser.deepCopyNodes(nodes); 13077230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } else { 13087230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy PathParser.updateNodes(mNodes, nodes); 13097230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 13107230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 13117230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 13127230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13137230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy /** 13147230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy * Clip path, which only has name and pathData. 13157230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy */ 13167230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy private static class VClipPath extends VPath { 13177230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public VClipPath() { 13187230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy // Empty constructor. 13197230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 13207230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13217230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public VClipPath(VClipPath copy) { 1322a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy super(copy); 1323a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 13247230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13257230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public void inflate(Resources r, AttributeSet attrs, Theme theme) { 13267230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy final TypedArray a = obtainAttributes(r, theme, attrs, 13277230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy R.styleable.VectorDrawableClipPath); 1328a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy updateStateFromTypedArray(a); 1329a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy a.recycle(); 1330a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 13317230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13327230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy private void updateStateFromTypedArray(TypedArray a) { 13337230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy // Account for any configuration changes. 13347230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy mChangingConfigurations |= a.getChangingConfigurations(); 13357230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13367230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy final String pathName = a.getString(R.styleable.VectorDrawableClipPath_name); 13377230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy if (pathName != null) { 13387230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy mPathName = pathName; 13397230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy } 13407230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13417230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy final String pathData = a.getString(R.styleable.VectorDrawableClipPath_pathData); 13427230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy if (pathData != null) { 13437230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy mNodes = PathParser.createNodesFromPathData(pathData); 1344a957eea78557cb47a91d44d9e6ee641c58cf1c07Romain Guy } 13458d0d4783a0206c5884bf0b958d181f450ba5207dRomain Guy } 13467230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy 13477230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy @Override 13487230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy public boolean isClipPath() { 13497230a74e9a36dfc6c4346c14e325bf07cd05b380Romain Guy return true; 135029d8997bd43b7c4ad37fc3d6f91eaafa74913c88Romain Guy } 1351759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy } 1352759ea80dca64ad652110a129e0d8bf93fea79f61Romain Guy 135385bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy /** 1354e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy * Normal path, which contains all the fill / paint information. 1355af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy */ 1356e45362cad94c014d8b3765cb102db0f8c0d92500Romain Guy private static class VFullPath extends VPath { 1357ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy ///////////////////////////////////////////////////// 1358ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy // Variables below need to be copied (deep copy if applicable) for mutation. 135970ca14e08ae197547ac412e8a1210e1ebdfb2eb1Romain Guy private int[] mThemeAttrs; 13603d58c03de0d8877b36cdb78b0ca8b5cac7f600e2Romain Guy 1361c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy int mStrokeColor = Color.TRANSPARENT; 13629d5316e3f56d138504565ff311145ac01621dff4Romain Guy float mStrokeWidth = 0; 1363c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 136401d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy int mFillColor = Color.TRANSPARENT; 136501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float mStrokeAlpha = 1.0f; 136601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy int mFillRule; 136701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float mFillAlpha = 1.0f; 136801d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float mTrimPathStart = 0; 136901d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float mTrimPathEnd = 1; 137001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy float mTrimPathOffset = 0; 137101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 137201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy Paint.Cap mStrokeLineCap = Paint.Cap.BUTT; 1373c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy Paint.Join mStrokeLineJoin = Paint.Join.MITER; 1374c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy float mStrokeMiterlimit = 4; 137501d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 137601d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy public VFullPath() { 137701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy // Empty constructor. 1378c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy } 1379c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 1380c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy public VFullPath(VFullPath copy) { 1381c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy super(copy); 138201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy mThemeAttrs = copy.mThemeAttrs; 1383c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 1384c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeColor = copy.mStrokeColor; 1385c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeWidth = copy.mStrokeWidth; 1386c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeAlpha = copy.mStrokeAlpha; 138701d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy mFillColor = copy.mFillColor; 1388c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mFillRule = copy.mFillRule; 1389c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mFillAlpha = copy.mFillAlpha; 139001d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy mTrimPathStart = copy.mTrimPathStart; 1391c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mTrimPathEnd = copy.mTrimPathEnd; 1392c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mTrimPathOffset = copy.mTrimPathOffset; 139301d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy 1394c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeLineCap = copy.mStrokeLineCap; 1395c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeLineJoin = copy.mStrokeLineJoin; 1396c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy mStrokeMiterlimit = copy.mStrokeMiterlimit; 1397c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy } 1398c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 13998b2f5267f16c295f12faab810527cd6311997e34Romain Guy private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) { 14008b2f5267f16c295f12faab810527cd6311997e34Romain Guy switch (id) { 14018b2f5267f16c295f12faab810527cd6311997e34Romain Guy case LINECAP_BUTT: 14028b2f5267f16c295f12faab810527cd6311997e34Romain Guy return Paint.Cap.BUTT; 14038b2f5267f16c295f12faab810527cd6311997e34Romain Guy case LINECAP_ROUND: 14048b2f5267f16c295f12faab810527cd6311997e34Romain Guy return Paint.Cap.ROUND; 14058b2f5267f16c295f12faab810527cd6311997e34Romain Guy case LINECAP_SQUARE: 14068b2f5267f16c295f12faab810527cd6311997e34Romain Guy return Paint.Cap.SQUARE; 14078b2f5267f16c295f12faab810527cd6311997e34Romain Guy default: 14088b2f5267f16c295f12faab810527cd6311997e34Romain Guy return defValue; 14098b2f5267f16c295f12faab810527cd6311997e34Romain Guy } 14108b2f5267f16c295f12faab810527cd6311997e34Romain Guy } 14118b2f5267f16c295f12faab810527cd6311997e34Romain Guy 14128b2f5267f16c295f12faab810527cd6311997e34Romain Guy private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) { 14138b2f5267f16c295f12faab810527cd6311997e34Romain Guy switch (id) { 1414c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy case LINEJOIN_MITER: 1415c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy return Paint.Join.MITER; 1416c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy case LINEJOIN_ROUND: 1417c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy return Paint.Join.ROUND; 1418c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy case LINEJOIN_BEVEL: 1419c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy return Paint.Join.BEVEL; 1420c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy default: 142101d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy return defValue; 142201d58e43ede5ca98cbebdd166f9b0c545032c01bRomain Guy } 14235c13d89c1332fcc499379b9064b891187b75ca32Chet Haase } 1424c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy 1425c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy @Override 1426c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy public boolean canApplyTheme() { 1427c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy return mThemeAttrs != null; 1428c1cd9ba335b293f11e1082447ef08e474710a05fRomain Guy } 14296926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy 14306926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy public void inflate(Resources r, AttributeSet attrs, Theme theme) { 14316926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy final TypedArray a = obtainAttributes(r, theme, attrs, 14326926c72e25b8dec3dd4b84af0819fa1937ae7296Romain Guy R.styleable.VectorDrawablePath); 1433026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy updateStateFromTypedArray(a); 1434746b7401ceb86b5f2805f8c0d3b39ac739152015Romain Guy a.recycle(); 1435a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy } 1436a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy 1437a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy private void updateStateFromTypedArray(TypedArray a) { 1438a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy // Account for any configuration changes. 1439a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy mChangingConfigurations |= a.getChangingConfigurations(); 1440a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy 1441a5aed0d58962a24c44728ffc46dc9e1ba2f9fda5Romain Guy // Extract the theme attributes, if any. 1442026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mThemeAttrs = a.extractThemeAttrs(); 1443026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 1444026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy final String pathName = a.getString(R.styleable.VectorDrawablePath_name); 1445026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy if (pathName != null) { 1446026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mPathName = pathName; 1447d27977d1a91d5a6b3cc9fa7664ac7e835e7bd895Romain Guy } 1448026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy 1449026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy final String pathData = a.getString(R.styleable.VectorDrawablePath_pathData); 1450026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy if (pathData != null) { 1451026c5e16704e817cac7d9c382914c947e34f87e0Romain Guy mNodes = PathParser.createNodesFromPathData(pathData); 1452c7d53494f1fbd9f9d74af89053ff9fdb1ccbac6cRomain Guy } 14539d5316e3f56d138504565ff311145ac01621dff4Romain Guy 1454e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mFillColor = a.getColor(R.styleable.VectorDrawablePath_fillColor, 1455e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mFillColor); 1456b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy mFillAlpha = a.getFloat(R.styleable.VectorDrawablePath_fillAlpha, 1457e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mFillAlpha); 1458e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeLineCap = getStrokeLineCap(a.getInt( 1459af636ebf5feb2837683fbfe965040cb706b32ec1Romain Guy R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap); 1460e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guy mStrokeLineJoin = getStrokeLineJoin(a.getInt( 1461f607bdc167f66b3e7003acaa4736ae46d78c1492Romain Guy R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin); 1462e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeMiterlimit = a.getFloat( 1463a674ab74e359ac73b4c4dd6b1a3a771836ac7e40Romain Guy R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit); 1464e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_strokeColor, 1465e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeColor); 1466e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeAlpha = a.getFloat(R.styleable.VectorDrawablePath_strokeAlpha, 1467e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeAlpha); 1468e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, 1469e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mStrokeWidth); 1470e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, 1471e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mTrimPathEnd); 1472e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mTrimPathOffset = a.getFloat( 1473e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset); 1474e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy mTrimPathStart = a.getFloat( 1475e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart); 1476e8e62a4a032a80409114a37908b5f18ab0080848Romain Guy } 14776620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 14783a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy @Override 14793a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy public void applyTheme(Theme t) { 14806620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy if (mThemeAttrs == null) { 14816620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy return; 14826620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 14836620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 14846620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath); 14856620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy updateStateFromTypedArray(a); 1486b45c0c9774bd19a9dbe77d149abae4e124b08bf6Romain Guy a.recycle(); 1487b45c0c9774bd19a9dbe77d149abae4e124b08bf6Romain Guy } 1488fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy 1489e2d345ea67e2960b37bfdc0fc8626d1bfa747404Romain Guy /* Setters and Getters, used by animator from AnimatedVectorDrawable. */ 149086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 149186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy int getStrokeColor() { 149286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return mStrokeColor; 14939d13fe25f4f10b25776b1dc5c858f9ebb0b28b30Romain Guy } 14941e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 1495b45c0c9774bd19a9dbe77d149abae4e124b08bf6Romain Guy @SuppressWarnings("unused") 1496fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy void setStrokeColor(int strokeColor) { 14971e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy mStrokeColor = strokeColor; 14981e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 14990a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy 150086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 150186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy float getStrokeWidth() { 150286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return mStrokeWidth; 150386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 150486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 150586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 150686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy void setStrokeWidth(float strokeWidth) { 150786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mStrokeWidth = strokeWidth; 150886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 150986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 151086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 151186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy float getStrokeAlpha() { 151286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return mStrokeAlpha; 151386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 151486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 15150a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy @SuppressWarnings("unused") 15160a41749953f35d33f61b3119e3161a82bb5fa59eRomain Guy void setStrokeAlpha(float strokeAlpha) { 151786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mStrokeAlpha = strokeAlpha; 15181e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy } 15191e45aae5de003657e5d18f74d34998f5de5db5b7Romain Guy 1520b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy @SuppressWarnings("unused") 1521b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy int getFillColor() { 1522b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy return mFillColor; 1523b146b1214ef6e4fc75d98779b22434335764cfdbRomain Guy } 15246620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 15256620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 15266620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy void setFillColor(int fillColor) { 15276620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy mFillColor = fillColor; 15286620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy } 15295b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 153086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 153186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy float getFillAlpha() { 153286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return mFillAlpha; 153386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 153486568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 153586568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 153686568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy void setFillAlpha(float fillAlpha) { 153786568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy mFillAlpha = fillAlpha; 153886568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 153986568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy 154086568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy @SuppressWarnings("unused") 154186568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy float getTrimPathStart() { 154286568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy return mTrimPathStart; 154386568198f2c83d4ce5c4cd692eda074ba9de9ed2Romain Guy } 154406f96e2652e4855b6520ad9dd70583677605b79aRomain Guy 15456620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 15465b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy void setTrimPathStart(float trimPathStart) { 15475b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTrimPathStart = trimPathStart; 15485b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 1549f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy 15505b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @SuppressWarnings("unused") 1551f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy float getTrimPathEnd() { 15525b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy return mTrimPathEnd; 15539d13fe25f4f10b25776b1dc5c858f9ebb0b28b30Romain Guy } 155403750a067e818ca7fbd0f590e2ff6a8fded21e6cRomain Guy 15556620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 1556f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy void setTrimPathEnd(float trimPathEnd) { 15575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy mTrimPathEnd = trimPathEnd; 1558f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy } 15596620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy 15606620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy @SuppressWarnings("unused") 15616620c6d413f972819fada92b574f0fa9e96d36c1Romain Guy float getTrimPathOffset() { 1562f219da5e32e85deb442468ee9a63bb28eb198557Romain Guy return mTrimPathOffset; 15635b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy } 15645b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy 15655b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy @SuppressWarnings("unused") 1566694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy void setTrimPathOffset(float trimPathOffset) { 1567694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy mTrimPathOffset = trimPathOffset; 1568fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy } 1569a674ab74e359ac73b4c4dd6b1a3a771836ac7e40Romain Guy } 15703a3fa1be9ab8e11edc660ecb35ae21ae0b5c8cc2Romain Guy} 1571694b519ac647fe998fd396fe0784cc8e179aadc4Romain Guy