VectorDrawable.java revision 8d0d24f7a2b1a59060aa18926984491691d3c667
1abb7d134c02ac60091108c491dafb00877093170John Hoford/*
2abb7d134c02ac60091108c491dafb00877093170John Hoford * Copyright (C) 2014 The Android Open Source Project
3abb7d134c02ac60091108c491dafb00877093170John Hoford *
4abb7d134c02ac60091108c491dafb00877093170John Hoford * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5abb7d134c02ac60091108c491dafb00877093170John Hoford * in compliance with the License. You may obtain a copy of the License at
6abb7d134c02ac60091108c491dafb00877093170John Hoford *
7abb7d134c02ac60091108c491dafb00877093170John Hoford * http://www.apache.org/licenses/LICENSE-2.0
8abb7d134c02ac60091108c491dafb00877093170John Hoford *
9abb7d134c02ac60091108c491dafb00877093170John Hoford * Unless required by applicable law or agreed to in writing, software distributed under the License
10abb7d134c02ac60091108c491dafb00877093170John Hoford * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11abb7d134c02ac60091108c491dafb00877093170John Hoford * or implied. See the License for the specific language governing permissions and limitations under
12abb7d134c02ac60091108c491dafb00877093170John Hoford * the License.
13abb7d134c02ac60091108c491dafb00877093170John Hoford */
14abb7d134c02ac60091108c491dafb00877093170John Hoford
15abb7d134c02ac60091108c491dafb00877093170John Hofordpackage android.graphics.drawable;
16abb7d134c02ac60091108c491dafb00877093170John Hoford
17b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.content.res.ColorStateList;
18abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources;
19abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.content.res.Resources.Theme;
204b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viveretteimport android.content.res.TypedArray;
21abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Canvas;
222af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghuiimport android.graphics.Color;
23abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.ColorFilter;
24abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Matrix;
25abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Paint;
26abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Path;
27abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PathMeasure;
28abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PixelFormat;
29b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuffColorFilter;
30abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Rect;
31abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Region;
32b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
33e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.ArrayMap;
34abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.AttributeSet;
35abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.Log;
36cf4832f69c8786b098ce18c24319021f8cd6733aztenghuiimport android.util.PathParser;
374b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport android.util.Xml;
38abb7d134c02ac60091108c491dafb00877093170John Hoford
39abb7d134c02ac60091108c491dafb00877093170John Hofordimport com.android.internal.R;
40abb7d134c02ac60091108c491dafb00877093170John Hoford
41abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParser;
42abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParserException;
434b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport org.xmlpull.v1.XmlPullParserFactory;
44abb7d134c02ac60091108c491dafb00877093170John Hoford
45abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.io.IOException;
46abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.util.ArrayList;
474d24caf1dec2babf273b18c99638fe2a0635ced4ztenghuiimport java.util.Stack;
484b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
49abb7d134c02ac60091108c491dafb00877093170John Hoford/**
50d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * This lets you create a drawable based on an XML vector graphic It can be
51d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * defined in an XML file with the <code>&lt;vector></code> element.
52abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
5346e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * The vector drawable has the following elements:
54abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
55abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
56177dffd869ff1f5bdf816faead01a7dc4980bf75ztenghui * <dt><code>&lt;vector></code></dt>
57e3c45e7a6b2a7d2176aa46ee482e299b54feeb9fztenghui * <dd>Used to defined a vector drawable</dd>
58abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;size></code></dt>
59abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Used to defined the intrinsic Width Height size of the drawable using
60d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <code>android:width</code> and <code>android:height</code></dd>
61abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;viewport></code></dt>
62abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
63d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * The size is defined using the attributes <code>android:viewportHeight</code>
64d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <code>android:viewportWidth</code></dd>
656d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dt><code>&lt;group></code></dt>
66452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>Defines a group of paths or subgroups, plus transformation information.
67452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * The transformations are defined in the same coordinates as the viewport.
68452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * And the transformations are applied in the order of scale, rotate then translate. </dd>
69452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:rotation</code>
70452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The degrees of rotation of the group.</dd></dt>
71452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:pivotX</code>
72452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The X coordinate of the pivot for the scale and rotation of the group</dd></dt>
73452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:pivotY</code>
74452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The Y coordinate of the pivot for the scale and rotation of the group</dd></dt>
75452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:scaleX</code>
76452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of scale on the X Coordinate</dd></dt>
77452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:scaleY</code>
78452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of scale on the Y coordinate</dd></dt>
79452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:translateX</code>
80452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of translation on the X coordinate</dd></dt>
81452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:translateY</code>
82452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of translation on the Y coordinate</dd></dt>
83abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;path></code></dt>
846d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dd>Defines paths to be drawn.
85abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
86abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:name</code>
87abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Defines the name of the path.</dd></dt>
88abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:pathData</code>
8946e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * <dd>Defines path string. This is using exactly same format as "d" attribute
9046e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * in the SVG's path data</dd></dt>
91abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:fill</code>
92abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Defines the color to fill the path (none if not present).</dd></dt>
93abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:stroke</code>
94d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Defines the color to draw the path outline (none if not present).</dd>
95d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * </dt>
96abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeWidth</code>
97abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The width a path stroke</dd></dt>
98abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeOpacity</code>
99abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The opacity of a path stroke</dd></dt>
100abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:fillOpacity</code>
101abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The opacity to fill the path with</dd></dt>
102abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathStart</code>
103abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The fraction of the path to trim from the start from 0 to 1</dd></dt>
104abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathEnd</code>
105abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
106abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathOffset</code>
107d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Shift trim region (allows showed region to include the start and end)
108d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * from 0 to 1</dd></dt>
109abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:clipToPath</code>
110abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Path will set the clip path</dd></dt>
111abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeLineCap</code>
112abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the linecap for a stroked path: butt, round, square</dd></dt>
113abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeLineJoin</code>
114abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the lineJoin for a stroked path: miter,round,bevel</dd></dt>
115abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeMiterLimit</code>
116abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the Miter limit for a stroked path</dd></dt>
117abb7d134c02ac60091108c491dafb00877093170John Hoford * </dl>
118abb7d134c02ac60091108c491dafb00877093170John Hoford * </dd>
119abb7d134c02ac60091108c491dafb00877093170John Hoford */
120abb7d134c02ac60091108c491dafb00877093170John Hofordpublic class VectorDrawable extends Drawable {
1219453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private static final String LOGTAG = VectorDrawable.class.getSimpleName();
1229453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
123abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_SIZE = "size";
124abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VIEWPORT = "viewport";
1256d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui    private static final String SHAPE_GROUP = "group";
126abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_PATH = "path";
127abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VECTOR = "vector";
128abb7d134c02ac60091108c491dafb00877093170John Hoford
129abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_BUTT = 0;
130abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_ROUND = 1;
131abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_SQUARE = 2;
1329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
133abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_MITER = 0;
134abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_ROUND = 1;
135abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_BEVEL = 2;
1369453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1374d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private static final boolean DBG_VECTOR_DRAWABLE = false;
1384d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
13955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private VectorDrawableState mVectorState;
140e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
141b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    private PorterDuffColorFilter mTintFilter;
142b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
14355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private boolean mMutated;
14455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
145abb7d134c02ac60091108c491dafb00877093170John Hoford    public VectorDrawable() {
14655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState = new VectorDrawableState();
147abb7d134c02ac60091108c491dafb00877093170John Hoford    }
148abb7d134c02ac60091108c491dafb00877093170John Hoford
1499453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
15016c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui        if (theme != null && state.canApplyTheme()) {
15116c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            // If we need to apply a theme, implicitly mutate.
15216c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            mVectorState = new VectorDrawableState(state);
1539453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            applyTheme(theme);
15416c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui        } else {
15516c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            mVectorState = state;
1569453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
157b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
158b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
159b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
160abb7d134c02ac60091108c491dafb00877093170John Hoford    }
161abb7d134c02ac60091108c491dafb00877093170John Hoford
16255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
16355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public Drawable mutate() {
16455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        if (!mMutated && super.mutate() == this) {
16555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVectorState = new VectorDrawableState(mVectorState);
16655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mMutated = true;
16755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
16855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return this;
16955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
17055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
171e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    Object getTargetByName(String name) {
17255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
173e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
174e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
175abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
176abb7d134c02ac60091108c491dafb00877093170John Hoford    public ConstantState getConstantState() {
17755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
17855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState;
179abb7d134c02ac60091108c491dafb00877093170John Hoford    }
180abb7d134c02ac60091108c491dafb00877093170John Hoford
1814554a6a5137d8e9bdfb623ad84ff344a48b7eb9dAlan Viverette    @Override
182abb7d134c02ac60091108c491dafb00877093170John Hoford    public void draw(Canvas canvas) {
1834b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        final int saveCount = canvas.save();
1844b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        final Rect bounds = getBounds();
1854b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.translate(bounds.left, bounds.top);
186ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
1874b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.restoreToCount(saveCount);
188abb7d134c02ac60091108c491dafb00877093170John Hoford    }
189abb7d134c02ac60091108c491dafb00877093170John Hoford
190abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
191e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getAlpha() {
192e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
193e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
194e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
195e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
196abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setAlpha(int alpha) {
1972af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
1982af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
199abb7d134c02ac60091108c491dafb00877093170John Hoford            invalidateSelf();
200abb7d134c02ac60091108c491dafb00877093170John Hoford        }
201abb7d134c02ac60091108c491dafb00877093170John Hoford    }
202abb7d134c02ac60091108c491dafb00877093170John Hoford
203abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
204abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setColorFilter(ColorFilter colorFilter) {
205b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
206b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (colorFilter != null) {
207b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Color filter overrides tint.
208b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = null;
209b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        } else if (state.mTint != null && state.mTintMode != null) {
210b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Restore the tint filter, if we need one.
211b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            final int color = state.mTint.getColorForState(getState(), Color.TRANSPARENT);
212b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
213b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            colorFilter = mTintFilter;
214b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
215b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
216b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        state.mVPathRenderer.setColorFilter(colorFilter);
217fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        invalidateSelf();
218abb7d134c02ac60091108c491dafb00877093170John Hoford    }
219abb7d134c02ac60091108c491dafb00877093170John Hoford
220abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
221b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    public void setTint(ColorStateList tint, Mode tintMode) {
222b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
223b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != tint || state.mTintMode != tintMode) {
224b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTint = tint;
225b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTintMode = tintMode;
226b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
227b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, tint, tintMode);
228b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
229b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            invalidateSelf();
230b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
231b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
232b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
233b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
234b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    protected boolean onStateChange(int[] stateSet) {
235b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
236b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != null && state.mTintMode != null) {
237b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
238b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
239b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            return true;
240b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
241b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        return false;
242b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
243b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
244b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
245abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getOpacity() {
246abb7d134c02ac60091108c491dafb00877093170John Hoford        return PixelFormat.TRANSLUCENT;
247abb7d134c02ac60091108c491dafb00877093170John Hoford    }
248abb7d134c02ac60091108c491dafb00877093170John Hoford
249abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
250abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicWidth() {
251ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
252abb7d134c02ac60091108c491dafb00877093170John Hoford    }
253abb7d134c02ac60091108c491dafb00877093170John Hoford
254abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
255abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicHeight() {
256ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
257abb7d134c02ac60091108c491dafb00877093170John Hoford    }
258abb7d134c02ac60091108c491dafb00877093170John Hoford
259abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
2609453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public boolean canApplyTheme() {
2619453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
2629453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
2639453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2649453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    @Override
2659453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public void applyTheme(Theme t) {
2669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        super.applyTheme(t);
2679453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2689453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        final VectorDrawableState state = mVectorState;
269ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer path = state.mVPathRenderer;
2709453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        if (path != null && path.canApplyTheme()) {
2719453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            path.applyTheme(t);
2729453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
2739453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
2749453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2754b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    /** @hide */
2764b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    public static VectorDrawable create(Resources resources, int rid) {
2774b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        try {
2784b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final XmlPullParser xpp = resources.getXml(rid);
2794b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final AttributeSet attrs = Xml.asAttributeSet(xpp);
2804b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
2814b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            factory.setNamespaceAware(true);
2824b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
2834b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final VectorDrawable drawable = new VectorDrawable();
2844b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            drawable.inflate(resources, xpp, attrs);
2854b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
2864b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            return drawable;
2874b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (XmlPullParserException e) {
2884b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
2894b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (IOException e) {
2904b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
2914b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        }
2924b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        return null;
2934b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    }
2944b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
2952af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    private static int applyAlpha(int color, float alpha) {
2962af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int alphaBytes = Color.alpha(color);
2972af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color &= 0x00FFFFFF;
2982af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
2992af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        return color;
3002af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    }
3012af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
3029cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    @Override
3039cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
3049cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            throws XmlPullParserException, IOException {
3058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
3069cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        updateStateFromTypedArray(a);
3079cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        a.recycle();
3089cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3099cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
31055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        inflateInternal(res, parser, attrs, theme);
3119cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3129cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
3139cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mVPathRenderer.setColorFilter(mTintFilter);
3149cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
3159cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3169cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    private void updateStateFromTypedArray(TypedArray a) {
3179cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
3189cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
3208e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
3218e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
3229cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        // Extract the theme attributes, if any.
3239cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
3249cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3259cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
3269cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tintMode != -1) {
3279cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
3289cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
3299cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3309cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
3319cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tint != null) {
3329cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTint = tint;
3339cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
3349cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
3359cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
33655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
3378e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
3388e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final VectorDrawableState state = mVectorState;
339ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
34055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        state.mVPathRenderer = pathRenderer;
3419453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
342abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noSizeTag = true;
343abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noViewportTag = true;
344abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noPathTag = true;
3459453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3464d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Use a stack to help to build the group tree.
3474d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // The top of the stack is always the current group.
3484d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
3494d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        groupStack.push(pathRenderer.mRootGroup);
350abb7d134c02ac60091108c491dafb00877093170John Hoford
351abb7d134c02ac60091108c491dafb00877093170John Hoford        int eventType = parser.getEventType();
352abb7d134c02ac60091108c491dafb00877093170John Hoford        while (eventType != XmlPullParser.END_DOCUMENT) {
353abb7d134c02ac60091108c491dafb00877093170John Hoford            if (eventType == XmlPullParser.START_TAG) {
3549453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                final String tagName = parser.getName();
3554d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final VGroup currentGroup = groupStack.peek();
3564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
357abb7d134c02ac60091108c491dafb00877093170John Hoford                if (SHAPE_PATH.equals(tagName)) {
3589453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    final VPath path = new VPath();
3599453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    path.inflate(res, attrs, theme);
3608d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(path);
361e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (path.getPathName() != null) {
36255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
363e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
364abb7d134c02ac60091108c491dafb00877093170John Hoford                    noPathTag = false;
3658e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= path.mChangingConfigurations;
366abb7d134c02ac60091108c491dafb00877093170John Hoford                } else if (SHAPE_SIZE.equals(tagName)) {
367ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                    pathRenderer.parseSize(res, attrs);
368abb7d134c02ac60091108c491dafb00877093170John Hoford                    noSizeTag = false;
3698e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
370abb7d134c02ac60091108c491dafb00877093170John Hoford                } else if (SHAPE_VIEWPORT.equals(tagName)) {
371ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                    pathRenderer.parseViewport(res, attrs);
372abb7d134c02ac60091108c491dafb00877093170John Hoford                    noViewportTag = false;
3738e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
3746d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
3754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    VGroup newChildGroup = new VGroup();
3764d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    newChildGroup.inflate(res, attrs, theme);
3778d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(newChildGroup);
3784d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.push(newChildGroup);
379e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (newChildGroup.getGroupName() != null) {
38055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
38155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                                newChildGroup);
382e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
3838e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
384abb7d134c02ac60091108c491dafb00877093170John Hoford                }
3854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
3864d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final String tagName = parser.getName();
3874d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                if (SHAPE_GROUP.equals(tagName)) {
3884d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.pop();
3894d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
390abb7d134c02ac60091108c491dafb00877093170John Hoford            }
391abb7d134c02ac60091108c491dafb00877093170John Hoford            eventType = parser.next();
392abb7d134c02ac60091108c491dafb00877093170John Hoford        }
3939453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3944d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the tree out for debug.
3954d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        if (DBG_VECTOR_DRAWABLE) {
3964d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
3976d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui        }
3986d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
39946e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui        if (noSizeTag || noViewportTag || noPathTag) {
4009453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final StringBuffer tag = new StringBuffer();
4019453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
402abb7d134c02ac60091108c491dafb00877093170John Hoford            if (noSizeTag) {
4039453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_SIZE);
404abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4059453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
406d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette            if (noViewportTag) {
407d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette                if (tag.length() > 0) {
408abb7d134c02ac60091108c491dafb00877093170John Hoford                    tag.append(" & ");
409abb7d134c02ac60091108c491dafb00877093170John Hoford                }
4109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_SIZE);
411abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4129453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
413d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette            if (noPathTag) {
414d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette                if (tag.length() > 0) {
415abb7d134c02ac60091108c491dafb00877093170John Hoford                    tag.append(" or ");
416abb7d134c02ac60091108c491dafb00877093170John Hoford                }
4179453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_PATH);
418abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4199453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
4209453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            throw new XmlPullParserException("no " + tag + " defined");
421abb7d134c02ac60091108c491dafb00877093170John Hoford        }
422abb7d134c02ac60091108c491dafb00877093170John Hoford    }
423abb7d134c02ac60091108c491dafb00877093170John Hoford
4244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
4254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        String indent = "";
4268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < level; i++) {
4274d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            indent += "    ";
4284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
4294d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the current node
4308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
4314d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                + " rotation is " + currentGroup.mRotate);
4328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
4338d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        // Then print all the children groups
4348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
4358d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            Object child = currentGroup.mChildren.get(i);
4368d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (child instanceof VGroup) {
4378d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                printGroupTree((VGroup) child, level + 1);
4388d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
4394d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
4404d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    }
4414d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
44255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
44355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public int getChangingConfigurations() {
44455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
44555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
44655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
4475c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    private static class VectorDrawableState extends ConstantState {
4489cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        int[] mThemeAttrs;
4495c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        int mChangingConfigurations;
450ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        VPathRenderer mVPathRenderer;
451b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        ColorStateList mTint;
452b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        Mode mTintMode;
4535c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
45455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Deep copy for mutate() or implicitly mutate.
4555c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public VectorDrawableState(VectorDrawableState copy) {
4565c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            if (copy != null) {
4579cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette                mThemeAttrs = copy.mThemeAttrs;
4585c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette                mChangingConfigurations = copy.mChangingConfigurations;
459ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
460b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTint = copy.mTint;
461b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = copy.mTintMode;
4625c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            }
4635c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
4645c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
46555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VectorDrawableState() {
46655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVPathRenderer = new VPathRenderer();
46755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
46855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
4695c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
4705c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable() {
4715c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, null, null);
4725c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
4735c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
4745c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
4755c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res) {
4765c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, res, null);
4775c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
4785c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
4795c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
4805c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res, Theme theme) {
4815c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, res, theme);
4825c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
4835c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
4845c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
4855c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public int getChangingConfigurations() {
4865c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return mChangingConfigurations;
4875c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
4885c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    }
4895c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
490ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui    private static class VPathRenderer {
4914d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        /* Right now the internal data structure is organized as a tree.
4924d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * Each node can be a group node, or a path.
4934d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * A group node can have groups or paths as children, but a path node has
4944d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * no children.
4954d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * One example can be:
4964d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                 Root Group
4974d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                /    |     \
4984d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *           Group    Path    Group
4994d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *          /     \             |
5004d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *         Path   Path         Path
5014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *
5024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         */
50355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables that only used temporarily inside the draw() call, so there
50455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // is no need for deep copying.
5054b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private final Path mPath = new Path();
5064b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private final Path mRenderPath = new Path();
5074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
50855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mFinalPathMatrix = new Matrix();
5094b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
5104b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mStrokePaint;
5114b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mFillPaint;
512fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        private ColorFilter mColorFilter;
513abb7d134c02ac60091108c491dafb00877093170John Hoford        private PathMeasure mPathMeasure;
5144b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
51555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
51655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
5178e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
51855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final VGroup mRootGroup;
5194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mBaseWidth = 0;
5204d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mBaseHeight = 0;
5214d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mViewportWidth = 0;
5224d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mViewportHeight = 0;
5232af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        private int mRootAlpha = 0xFF;
5249453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
52555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
526abb7d134c02ac60091108c491dafb00877093170John Hoford
527ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer() {
5284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mRootGroup = new VGroup();
529abb7d134c02ac60091108c491dafb00877093170John Hoford        }
5309453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
5312af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public void setRootAlpha(int alpha) {
5322af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mRootAlpha = alpha;
5332af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
5342af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
5352af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public int getRootAlpha() {
5362af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            return mRootAlpha;
5372af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
5382af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
539ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer(VPathRenderer copy) {
54055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
541abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseWidth = copy.mBaseWidth;
542abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseHeight = copy.mBaseHeight;
543abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportWidth = copy.mViewportHeight;
544abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportHeight = copy.mViewportHeight;
5458e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations = copy.mChangingConfigurations;
54655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootAlpha = copy.mRootAlpha;
547abb7d134c02ac60091108c491dafb00877093170John Hoford        }
548abb7d134c02ac60091108c491dafb00877093170John Hoford
5499453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public boolean canApplyTheme() {
5504d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // If one of the paths can apply theme, then return true;
5514d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return recursiveCanApplyTheme(mRootGroup);
5524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
5534d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
5544d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private boolean recursiveCanApplyTheme(VGroup currentGroup) {
5554d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, if there is one path return true,
5564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // then we return true for the whole tree.
5578d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
5588d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
5598d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
5608d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
5618d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
5628d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
5638d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()
5648d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            || recursiveCanApplyTheme(childGroup)) {
5658d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
5668d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
5678d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
5688d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
5698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
5708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
5718d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
5724d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
5734d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
5749453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            return false;
5759453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
5769453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
5779453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void applyTheme(Theme t) {
5784d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Apply theme to every path of the tree.
5794d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            recursiveApplyTheme(mRootGroup, t);
5804d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
5814d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
5824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
5834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, apply theme to all paths which
5844d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // can apply theme.
5858d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
5868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
5878d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
5888d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
5898d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
5908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()) {
5918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childGroup.applyTheme(t);
5928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
5938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    recursiveApplyTheme(childGroup, t);
5948d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
5958d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
5968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
5978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childPath.applyTheme(t);
5988d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
5994d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
6004d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
601abb7d134c02ac60091108c491dafb00877093170John Hoford        }
602abb7d134c02ac60091108c491dafb00877093170John Hoford
603fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        public void setColorFilter(ColorFilter colorFilter) {
604fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mColorFilter = colorFilter;
605fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
606fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mFillPaint != null) {
607fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                mFillPaint.setColorFilter(colorFilter);
608fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            }
609fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
610fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mStrokePaint != null) {
611fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                mStrokePaint.setColorFilter(colorFilter);
612fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            }
6136d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
614fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        }
615fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
6164d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
6172af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                float currentAlpha, Canvas canvas, int w, int h) {
6184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Calculate current group's matrix by preConcat the parent's and
6194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // and the current one on the top of the stack.
6204d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
6214d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Mi the local matrix at level i of the group tree.
6224d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
6234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
6244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
6254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
6262af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            float stackedAlpha = currentAlpha * currentGroup.mGroupAlpha;
6278d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
6288d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            // Draw the group tree in the same order as the XML file.
6298d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
6308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = currentGroup.mChildren.get(i);
6318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
6328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
6338d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
6348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            stackedAlpha, canvas, w, h);
6358d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
6368d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
6378d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawPath(currentGroup, childPath, stackedAlpha, canvas, w, h);
6388d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
639abb7d134c02ac60091108c491dafb00877093170John Hoford            }
6404d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
641abb7d134c02ac60091108c491dafb00877093170John Hoford
6424d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public void draw(Canvas canvas, int w, int h) {
6434d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Travese the tree in pre-order to draw.
6442af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, ((float) mRootAlpha) / 0xFF, canvas, w, h);
645abb7d134c02ac60091108c491dafb00877093170John Hoford        }
646abb7d134c02ac60091108c491dafb00877093170John Hoford
6478d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        private void drawPath(VGroup vGroup, VPath vPath, float stackedAlpha,
6488d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Canvas canvas, int w, int h) {
6499453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
650abb7d134c02ac60091108c491dafb00877093170John Hoford
6514d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mFinalPathMatrix.set(vGroup.mStackedMatrix);
6524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mFinalPathMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
6538e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mFinalPathMatrix.postTranslate(
6548e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
655abb7d134c02ac60091108c491dafb00877093170John Hoford
6568d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            vPath.toPath(mPath);
6578d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final Path path = mPath;
658abb7d134c02ac60091108c491dafb00877093170John Hoford
6598d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
6608d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
6618d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float end = (vPath.mTrimPathEnd + vPath.mTrimPathOffset) % 1.0f;
6629453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6638d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (mPathMeasure == null) {
6648d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure = new PathMeasure();
6654b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette                }
6668d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                mPathMeasure.setPath(mPath, false);
6678d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
6688d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float len = mPathMeasure.getLength();
6698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                start = start * len;
6708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                end = end * len;
6718d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                path.reset();
6728d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (start > end) {
6738d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(start, len, path, true);
6748d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(0f, end, path, true);
6758d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else {
6768d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(start, end, path, true);
6778d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
6788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                path.rLineTo(0, 0); // fix bug in measure
6798d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
6804b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
6818d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.reset();
6829453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6838d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.addPath(path, mFinalPathMatrix);
6844b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
6858d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (vPath.mClip) {
6868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                canvas.clipPath(mRenderPath, Region.Op.REPLACE);
6878d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            } else {
6888d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (vPath.mFillColor != 0) {
6898d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mFillPaint == null) {
6908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint = new Paint();
6918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setColorFilter(mColorFilter);
6928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
6938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setAntiAlias(true);
69463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                    }
6958d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mFillPaint.setColor(applyAlpha(vPath.mFillColor, stackedAlpha));
6968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, mFillPaint);
6978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
69863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
6998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (vPath.mStrokeColor != 0) {
7008d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mStrokePaint == null) {
7018d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint = new Paint();
7028d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setColorFilter(mColorFilter);
7038d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
7048d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setAntiAlias(true);
7058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
7064b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
7078d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    final Paint strokePaint = mStrokePaint;
7088d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (vPath.mStrokeLineJoin != null) {
7098d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
7108d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
711abb7d134c02ac60091108c491dafb00877093170John Hoford
7128d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (vPath.mStrokeLineCap != null) {
7138d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        strokePaint.setStrokeCap(vPath.mStrokeLineCap);
7148d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
71563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
7168d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
71763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
7188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setColor(applyAlpha(vPath.mStrokeColor, stackedAlpha));
7198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
7208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
72163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                }
722abb7d134c02ac60091108c491dafb00877093170John Hoford            }
723abb7d134c02ac60091108c491dafb00877093170John Hoford        }
724abb7d134c02ac60091108c491dafb00877093170John Hoford
725abb7d134c02ac60091108c491dafb00877093170John Hoford        private void parseViewport(Resources r, AttributeSet attrs)
726abb7d134c02ac60091108c491dafb00877093170John Hoford                throws XmlPullParserException {
7274b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
7288e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
7298e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
7308e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
7318e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
7328e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mViewportWidth = a.getFloat(
7338e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableViewport_viewportWidth, mViewportWidth);
7348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mViewportHeight = a.getFloat(
7358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableViewport_viewportHeight, mViewportHeight);
736fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
737fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mViewportWidth <= 0) {
738fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
739fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<viewport> tag requires viewportWidth > 0");
740fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            } else if (mViewportHeight <= 0) {
741fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
742fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<viewport> tag requires viewportHeight > 0");
743abb7d134c02ac60091108c491dafb00877093170John Hoford            }
744fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
745abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
746abb7d134c02ac60091108c491dafb00877093170John Hoford        }
747abb7d134c02ac60091108c491dafb00877093170John Hoford
748abb7d134c02ac60091108c491dafb00877093170John Hoford        private void parseSize(Resources r, AttributeSet attrs)
7498d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                throws XmlPullParserException {
7504b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
7518e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
7528e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
7538e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
7548e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
755fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, mBaseWidth);
756fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, mBaseHeight);
757fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
758fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mBaseWidth <= 0) {
759fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
760fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<size> tag requires width > 0");
761fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            } else if (mBaseHeight <= 0) {
762fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
763fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<size> tag requires height > 0");
764abb7d134c02ac60091108c491dafb00877093170John Hoford            }
765fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
766abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
767abb7d134c02ac60091108c491dafb00877093170John Hoford        }
7684b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
769abb7d134c02ac60091108c491dafb00877093170John Hoford    }
770abb7d134c02ac60091108c491dafb00877093170John Hoford
771e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    static class VGroup {
77255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
77355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // the parents' local matrices with the current one.
77455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mStackedMatrix = new Matrix();
77555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
77655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
77755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
7788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
779abb7d134c02ac60091108c491dafb00877093170John Hoford
78063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mRotate = 0;
78163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotX = 0;
78263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotY = 0;
783452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleX = 1;
784452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleY = 1;
785452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateX = 0;
786452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateY = 0;
7872af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        private float mGroupAlpha = 1;
7884d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
78955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mLocalMatrix is updated based on the update of transformation information,
79055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // either parsed from the XML or by animation.
7914d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private final Matrix mLocalMatrix = new Matrix();
7928e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
79363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private int[] mThemeAttrs;
794e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        private String mGroupName = null;
795e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
79655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
79755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRotate = copy.mRotate;
79855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotX = copy.mPivotX;
79955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotY = copy.mPivotY;
80055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleX = copy.mScaleX;
80155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleY = copy.mScaleY;
80255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateX = copy.mTranslateX;
80355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateY = copy.mTranslateY;
80455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupAlpha = copy.mGroupAlpha;
80555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
80655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupName = copy.mGroupName;
80755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
80855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mGroupName != null) {
80955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                targetsMap.put(mGroupName, this);
81055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
81155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
81255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mLocalMatrix.set(copy.mLocalMatrix);
81355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
8148d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = copy.mChildren;
8158d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
8168d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object copyChild = children.get(i);
8178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (copyChild instanceof VGroup) {
8188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup copyGroup = (VGroup) copyChild;
8198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
8208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (copyChild instanceof VPath) {
8218d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath copyPath = (VPath) copyChild;
8228d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath newPath = new VPath(copyPath);
8238d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(newPath);
8248d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (newPath.mPathName != null) {
8258d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        targetsMap.put(newPath.mPathName, newPath);
8268d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
82755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                }
82855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
82955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
83055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
83155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup() {
83255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
83355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
834e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        /* Getter and Setter */
835e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getRotation() {
836e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mRotate;
837e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
838e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
839e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setRotation(float rotation) {
840e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (rotation != mRotate) {
841e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mRotate = rotation;
842e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
843e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
844e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
845e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
846e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotX() {
847e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotX;
848e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
849e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
850e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotX(float pivotX) {
851e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotX != mPivotX) {
852e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotX = pivotX;
853e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
854e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
855e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
856e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
857e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotY() {
858e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotY;
859e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
860e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
861e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotY(float pivotY) {
862e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotY != mPivotY) {
863e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotY = pivotY;
864e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
865e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
866e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
867e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
868e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleX() {
869e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleX;
870e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
8714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
872e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleX(float scaleX) {
873e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleX != mScaleX) {
874e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleX = scaleX;
875e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
876e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
877e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
878e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
879e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleY() {
880e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleY;
881e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
882e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
883e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleY(float scaleY) {
884e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleY != mScaleY) {
885e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleY = scaleY;
886e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
887e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
888e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
889e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
890e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateX() {
891e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateX;
892e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
893e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
894e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateX(float translateX) {
895e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateX != mTranslateX) {
896e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateX = translateX;
897e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
898e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
899e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
900e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
901e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateY() {
902e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateY;
903e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
904e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
905e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateY(float translateY) {
906e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateY != mTranslateY) {
907e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateY = translateY;
908e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
909e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
910e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
911e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
912e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getAlpha() {
913e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mGroupAlpha;
914e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
915e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
916e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setAlpha(float groupAlpha) {
917e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (groupAlpha != mGroupAlpha) {
918e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mGroupAlpha = groupAlpha;
919e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
920e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
921e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
922e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public String getGroupName() {
923e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mGroupName;
9244d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
9254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9264d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public Matrix getLocalMatrix() {
9274d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return mLocalMatrix;
9284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
9294d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9304d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public boolean canApplyTheme() {
9314d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return mThemeAttrs != null;
9324d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
9334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
9358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = obtainAttributes(res, theme, attrs,
9368e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableGroup);
9378e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
9388e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            a.recycle();
9398e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
9408e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
9418e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private void updateStateFromTypedArray(TypedArray a) {
9428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
9438e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
94463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
9458e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Extract the theme attributes, if any.
9468e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mThemeAttrs = a.extractThemeAttrs();
94763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
94863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
94963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
95063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
951452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
952452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
953452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
954452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
9552af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
95663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
9578e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
9588e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (groupName != null) {
9598e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                mGroupName = groupName;
96063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            }
96163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
9628e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateLocalMatrix();
9638e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
9644d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9658e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void applyTheme(Theme t) {
9668e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (mThemeAttrs == null) {
9678e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                return;
9684d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
9694d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
9708e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
9718e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
97263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
97363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        }
97463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
9754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void updateLocalMatrix() {
9764d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // The order we apply is the same as the
9774d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
9784d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.reset();
9794d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
9804d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
9814d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
9824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
9834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
984abb7d134c02ac60091108c491dafb00877093170John Hoford    }
985abb7d134c02ac60091108c491dafb00877093170John Hoford
986cf4832f69c8786b098ce18c24319021f8cd6733aztenghui    private static class VPath {
98755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
98855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
9899453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private int[] mThemeAttrs;
9909453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
991abb7d134c02ac60091108c491dafb00877093170John Hoford        int mStrokeColor = 0;
992abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeWidth = 0;
993abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeOpacity = Float.NaN;
9942af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int mFillColor = Color.BLACK;
995abb7d134c02ac60091108c491dafb00877093170John Hoford        int mFillRule;
996abb7d134c02ac60091108c491dafb00877093170John Hoford        float mFillOpacity = Float.NaN;
997abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathStart = 0;
998abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathEnd = 1;
999abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathOffset = 0;
10009453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1001abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean mClip = false;
10024b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
10034b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
1004abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeMiterlimit = 4;
10059453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
100655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private PathParser.PathDataNode[] mNodes = null;
10078d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        String mPathName;
100855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private int mChangingConfigurations;
1009abb7d134c02ac60091108c491dafb00877093170John Hoford
10109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public VPath() {
10119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            // Empty constructor.
10129453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
10139453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
101455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VPath(VPath copy) {
101555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
101655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
101755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeColor = copy.mStrokeColor;
101855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeWidth = copy.mStrokeWidth;
101955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeOpacity = copy.mStrokeOpacity;
102055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillColor = copy.mFillColor;
102155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillRule = copy.mFillRule;
102255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillOpacity = copy.mFillOpacity;
102355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathStart = copy.mTrimPathStart;
102455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathEnd = copy.mTrimPathEnd;
102555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathOffset = copy.mTrimPathOffset;
102655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
102755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mClip = copy.mClip;
102855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineCap = copy.mStrokeLineCap;
102955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
103055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
103155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
103255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
103355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPathName = copy.mPathName;
103455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
103555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
103655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
1037abb7d134c02ac60091108c491dafb00877093170John Hoford        public void toPath(Path path) {
1038abb7d134c02ac60091108c491dafb00877093170John Hoford            path.reset();
103955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mNodes != null) {
104055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
1041abb7d134c02ac60091108c491dafb00877093170John Hoford            }
1042abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1043abb7d134c02ac60091108c491dafb00877093170John Hoford
1044e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public String getPathName() {
1045e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPathName;
1046abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1047abb7d134c02ac60091108c491dafb00877093170John Hoford
10487f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
10497f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
10507f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_BUTT:
10517f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.BUTT;
10527f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_ROUND:
10537f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.ROUND;
10547f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_SQUARE:
10557f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.SQUARE;
10567f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
10577f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
10587f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
10597f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
10607f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
10617f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
10627f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
10637f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_MITER:
10647f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.MITER;
10657f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_ROUND:
10667f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.ROUND;
10677f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_BEVEL:
10687f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.BEVEL;
10697f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
10707f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
10717f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
10727f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
10737f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
1074eb034fbca40006c55db143047eb628c4b657730aztenghui        /* Setters and Getters, mostly used by animator from AnimatedVectorDrawable. */
1075eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1076eb034fbca40006c55db143047eb628c4b657730aztenghui        public PathParser.PathDataNode[] getPathData() {
107755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            return mNodes;
1078eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1079eb034fbca40006c55db143047eb628c4b657730aztenghui
1080eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
108155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
108255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
1083eb034fbca40006c55db143047eb628c4b657730aztenghui                // This should not happen in the middle of animation.
108455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                mNodes = PathParser.deepCopyNodes(nodes);
1085eb034fbca40006c55db143047eb628c4b657730aztenghui            } else {
108655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                PathParser.updateNodes(mNodes, nodes);
1087eb034fbca40006c55db143047eb628c4b657730aztenghui            }
1088eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1089eb034fbca40006c55db143047eb628c4b657730aztenghui
1090eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1091e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int getStroke() {
1092e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeColor;
1093e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1094e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1095eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1096e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStroke(int strokeColor) {
1097e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeColor = strokeColor;
1098e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1099e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1100eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1101e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeWidth() {
1102e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeWidth;
1103e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1104e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1105eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1106e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeWidth(float strokeWidth) {
1107e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeWidth = strokeWidth;
1108e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1109e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1110eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1111e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeOpacity() {
1112e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeOpacity;
1113e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1114e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1115eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1116e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeOpacity(float strokeOpacity) {
1117e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeOpacity = strokeOpacity;
1118e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1119e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1120eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1121e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int getFill() {
1122e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillColor;
1123e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1124e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1125eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1126e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setFill(int fillColor) {
1127e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillColor = fillColor;
1128e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1129e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1130eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1131e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getFillOpacity() {
1132e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillOpacity;
1133e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1134e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1135eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1136e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setFillOpacity(float fillOpacity) {
1137e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillOpacity = fillOpacity;
1138e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1139e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1140eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1141e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathStart() {
1142e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathStart;
1143e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1144e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1145eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1146e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathStart(float trimPathStart) {
1147e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathStart = trimPathStart;
1148e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1149e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1150eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1151e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathEnd() {
1152e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathEnd;
1153e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1154e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1155eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1156e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathEnd(float trimPathEnd) {
1157e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathEnd = trimPathEnd;
1158e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1159e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1160eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1161e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathOffset() {
1162e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathOffset;
1163e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1164e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1165eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1166e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathOffset(float trimPathOffset) {
1167e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathOffset = trimPathOffset;
1168e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1169e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
11708e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public boolean canApplyTheme() {
11718e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            return mThemeAttrs != null;
11728e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
11738e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
11749453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
11759453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
11768e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
1177abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
1178abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1179abb7d134c02ac60091108c491dafb00877093170John Hoford
11808e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private void updateStateFromTypedArray(TypedArray a) {
11818e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
11828e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
11839453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
11848e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Extract the theme attributes, if any.
11858e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mThemeAttrs = a.extractThemeAttrs();
11869453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
11877f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
118855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
11898e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mPathName = a.getString(R.styleable.VectorDrawablePath_name);
119055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mNodes = PathParser.createNodesFromPathData(a.getString(
11918e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawablePath_pathData));
119255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
11937f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
11947f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
11957f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeLineCap = getStrokeLineCap(a.getInt(
11967f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
11977f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
11987f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
11997f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeMiterlimit = a.getFloat(
12007f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
12017f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
12027f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeOpacity = a.getFloat(
12037f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
12047f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
12057f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
12067f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathOffset = a.getFloat(
12077f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
12087f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathStart = a.getFloat(
12097f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
12109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            updateColorAlphas();
12128e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
12138e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
12148e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void applyTheme(Theme t) {
12158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (mThemeAttrs == null) {
12168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                return;
12178e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            }
12188e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
12198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
12208e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
122163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
12229453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
12239453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12249453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private void updateColorAlphas() {
12259453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            if (!Float.isNaN(mFillOpacity)) {
12262af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                mFillColor = applyAlpha(mFillColor, mFillOpacity);
12279453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            }
12289453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12299453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            if (!Float.isNaN(mStrokeOpacity)) {
12302af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity);
12319453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            }
12329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
1233abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1234abb7d134c02ac60091108c491dafb00877093170John Hoford}
1235