VectorDrawable.java revision 738177caf6a755a59ca6b17bb968be0aa4e8e10f
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;
21482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghuiimport android.graphics.Bitmap;
22abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Canvas;
232af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghuiimport android.graphics.Color;
24abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.ColorFilter;
25abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Matrix;
26abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Paint;
27abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Path;
28abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PathMeasure;
29abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.PixelFormat;
30b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuffColorFilter;
31abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Rect;
32abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.graphics.Region;
33b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viveretteimport android.graphics.PorterDuff.Mode;
34e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghuiimport android.util.ArrayMap;
35abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.AttributeSet;
36738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghuiimport android.util.LayoutDirection;
37abb7d134c02ac60091108c491dafb00877093170John Hofordimport android.util.Log;
38cf4832f69c8786b098ce18c24319021f8cd6733aztenghuiimport android.util.PathParser;
394b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport android.util.Xml;
40abb7d134c02ac60091108c491dafb00877093170John Hoford
41abb7d134c02ac60091108c491dafb00877093170John Hofordimport com.android.internal.R;
42abb7d134c02ac60091108c491dafb00877093170John Hoford
43abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParser;
44abb7d134c02ac60091108c491dafb00877093170John Hofordimport org.xmlpull.v1.XmlPullParserException;
454b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viveretteimport org.xmlpull.v1.XmlPullParserFactory;
46abb7d134c02ac60091108c491dafb00877093170John Hoford
47abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.io.IOException;
48abb7d134c02ac60091108c491dafb00877093170John Hofordimport java.util.ArrayList;
494d24caf1dec2babf273b18c99638fe2a0635ced4ztenghuiimport java.util.Stack;
504b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
51abb7d134c02ac60091108c491dafb00877093170John Hoford/**
52d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * This lets you create a drawable based on an XML vector graphic It can be
53d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * defined in an XML file with the <code>&lt;vector></code> element.
54abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
5546e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * The vector drawable has the following elements:
56abb7d134c02ac60091108c491dafb00877093170John Hoford * <p/>
57abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
58177dffd869ff1f5bdf816faead01a7dc4980bf75ztenghui * <dt><code>&lt;vector></code></dt>
59e3c45e7a6b2a7d2176aa46ee482e299b54feeb9fztenghui * <dd>Used to defined a vector drawable</dd>
60abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;size></code></dt>
61abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Used to defined the intrinsic Width Height size of the drawable using
62d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <code>android:width</code> and <code>android:height</code></dd>
63abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;viewport></code></dt>
64abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
65d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * The size is defined using the attributes <code>android:viewportHeight</code>
66d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <code>android:viewportWidth</code></dd>
676d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dt><code>&lt;group></code></dt>
68452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>Defines a group of paths or subgroups, plus transformation information.
69452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * The transformations are defined in the same coordinates as the viewport.
70452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * And the transformations are applied in the order of scale, rotate then translate. </dd>
71452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:rotation</code>
72452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The degrees of rotation of the group.</dd></dt>
73452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:pivotX</code>
74452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The X coordinate of the pivot for the scale and rotation of the group</dd></dt>
75452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:pivotY</code>
76452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The Y coordinate of the pivot for the scale and rotation of the group</dd></dt>
77452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:scaleX</code>
78452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of scale on the X Coordinate</dd></dt>
79452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:scaleY</code>
80452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of scale on the Y coordinate</dd></dt>
81452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:translateX</code>
82452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of translation on the X coordinate</dd></dt>
83452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dt><code>android:translateY</code>
84452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui * <dd>The amount of translation on the Y coordinate</dd></dt>
85abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>&lt;path></code></dt>
866d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui * <dd>Defines paths to be drawn.
87abb7d134c02ac60091108c491dafb00877093170John Hoford * <dl>
88abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:name</code>
89abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Defines the name of the path.</dd></dt>
90abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:pathData</code>
9146e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * <dd>Defines path string. This is using exactly same format as "d" attribute
9246e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui * in the SVG's path data</dd></dt>
93abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:fill</code>
94abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Defines the color to fill the path (none if not present).</dd></dt>
95abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:stroke</code>
96d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Defines the color to draw the path outline (none if not present).</dd>
97d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * </dt>
98abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeWidth</code>
99abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The width a path stroke</dd></dt>
100abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeOpacity</code>
101abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The opacity of a path stroke</dd></dt>
102abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:fillOpacity</code>
103abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The opacity to fill the path with</dd></dt>
104abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathStart</code>
105abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The fraction of the path to trim from the start from 0 to 1</dd></dt>
106abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathEnd</code>
107abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
108abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:trimPathOffset</code>
109d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * <dd>Shift trim region (allows showed region to include the start and end)
110d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette * from 0 to 1</dd></dt>
111abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:clipToPath</code>
112abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Path will set the clip path</dd></dt>
113abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeLineCap</code>
114abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the linecap for a stroked path: butt, round, square</dd></dt>
115abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeLineJoin</code>
116abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the lineJoin for a stroked path: miter,round,bevel</dd></dt>
117abb7d134c02ac60091108c491dafb00877093170John Hoford * <dt><code>android:strokeMiterLimit</code>
118abb7d134c02ac60091108c491dafb00877093170John Hoford * <dd>Sets the Miter limit for a stroked path</dd></dt>
119abb7d134c02ac60091108c491dafb00877093170John Hoford * </dl>
120abb7d134c02ac60091108c491dafb00877093170John Hoford * </dd>
121abb7d134c02ac60091108c491dafb00877093170John Hoford */
122abb7d134c02ac60091108c491dafb00877093170John Hofordpublic class VectorDrawable extends Drawable {
1239453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private static final String LOGTAG = VectorDrawable.class.getSimpleName();
1249453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
125abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_SIZE = "size";
126abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VIEWPORT = "viewport";
1276d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui    private static final String SHAPE_GROUP = "group";
128abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_PATH = "path";
129abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final String SHAPE_VECTOR = "vector";
130abb7d134c02ac60091108c491dafb00877093170John Hoford
131abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_BUTT = 0;
132abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_ROUND = 1;
133abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINECAP_SQUARE = 2;
1349453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
135abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_MITER = 0;
136abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_ROUND = 1;
137abb7d134c02ac60091108c491dafb00877093170John Hoford    private static final int LINEJOIN_BEVEL = 2;
1389453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1394d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private static final boolean DBG_VECTOR_DRAWABLE = false;
1404d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
14155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private VectorDrawableState mVectorState;
142e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
143b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    private PorterDuffColorFilter mTintFilter;
144b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
14555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private boolean mMutated;
14655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
147482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
148482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    // caching the bitmap by default is allowed.
149482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    private boolean mAllowCaching = true;
150482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
151abb7d134c02ac60091108c491dafb00877093170John Hoford    public VectorDrawable() {
15255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState = new VectorDrawableState();
153abb7d134c02ac60091108c491dafb00877093170John Hoford    }
154abb7d134c02ac60091108c491dafb00877093170John Hoford
1559453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
15616c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui        if (theme != null && state.canApplyTheme()) {
15716c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            // If we need to apply a theme, implicitly mutate.
15816c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            mVectorState = new VectorDrawableState(state);
1599453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            applyTheme(theme);
16016c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui        } else {
16116c1bd5db8f4f18e1eee8b19006bba5f06a88123ztenghui            mVectorState = state;
1629453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
163b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
164b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
165b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
166abb7d134c02ac60091108c491dafb00877093170John Hoford    }
167abb7d134c02ac60091108c491dafb00877093170John Hoford
16855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
16955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public Drawable mutate() {
17055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        if (!mMutated && super.mutate() == this) {
17155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVectorState = new VectorDrawableState(mVectorState);
17255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mMutated = true;
17355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
17455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return this;
17555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
17655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
177e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    Object getTargetByName(String name) {
17855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
179e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
180e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
181abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
182abb7d134c02ac60091108c491dafb00877093170John Hoford    public ConstantState getConstantState() {
18355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
18455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return mVectorState;
185abb7d134c02ac60091108c491dafb00877093170John Hoford    }
186abb7d134c02ac60091108c491dafb00877093170John Hoford
1874554a6a5137d8e9bdfb623ad84ff344a48b7eb9dAlan Viverette    @Override
188abb7d134c02ac60091108c491dafb00877093170John Hoford    public void draw(Canvas canvas) {
1894b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        final int saveCount = canvas.save();
1904b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        final Rect bounds = getBounds();
191738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        final boolean needMirroring = needMirroring();
192738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
1934b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.translate(bounds.left, bounds.top);
194738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (needMirroring) {
195738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            canvas.translate(bounds.width(), 0);
196738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            canvas.scale(-1.0f, 1.0f);
197738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
198482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
199482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        if (!mAllowCaching) {
200482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mVectorState.mVPathRenderer.draw(canvas, bounds.width(), bounds.height());
201482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        } else {
202482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            Bitmap bitmap = mVectorState.mCachedBitmap;
203482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            if (bitmap == null || !mVectorState.canReuseCache(bounds.width(),
204482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    bounds.height())) {
205482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                bitmap = Bitmap.createBitmap(bounds.width(), bounds.height(),
206482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                        Bitmap.Config.ARGB_8888);
207482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                Canvas tmpCanvas = new Canvas(bitmap);
208482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                mVectorState.mVPathRenderer.draw(tmpCanvas, bounds.width(), bounds.height());
209482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                mVectorState.mCachedBitmap = bitmap;
210482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
211482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                mVectorState.updateCacheStates();
212482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
213482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            canvas.drawBitmap(bitmap, null, bounds, null);
214482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
215738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
2164b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        canvas.restoreToCount(saveCount);
217abb7d134c02ac60091108c491dafb00877093170John Hoford    }
218abb7d134c02ac60091108c491dafb00877093170John Hoford
219abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
220e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    public int getAlpha() {
221e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
222e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    }
223e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
224e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    @Override
225abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setAlpha(int alpha) {
2262af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
2272af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
228abb7d134c02ac60091108c491dafb00877093170John Hoford            invalidateSelf();
229abb7d134c02ac60091108c491dafb00877093170John Hoford        }
230abb7d134c02ac60091108c491dafb00877093170John Hoford    }
231abb7d134c02ac60091108c491dafb00877093170John Hoford
232abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
233abb7d134c02ac60091108c491dafb00877093170John Hoford    public void setColorFilter(ColorFilter colorFilter) {
234b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
235b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (colorFilter != null) {
236b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Color filter overrides tint.
237b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = null;
238b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        } else if (state.mTint != null && state.mTintMode != null) {
239b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            // Restore the tint filter, if we need one.
240b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            final int color = state.mTint.getColorForState(getState(), Color.TRANSPARENT);
241b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = new PorterDuffColorFilter(color, state.mTintMode);
242b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            colorFilter = mTintFilter;
243b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
244b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
245b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        state.mVPathRenderer.setColorFilter(colorFilter);
246fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        invalidateSelf();
247abb7d134c02ac60091108c491dafb00877093170John Hoford    }
248abb7d134c02ac60091108c491dafb00877093170John Hoford
249abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
250b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    public void setTint(ColorStateList tint, Mode tintMode) {
251b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
252b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != tint || state.mTintMode != tintMode) {
253b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTint = tint;
254b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            state.mTintMode = tintMode;
255b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
256b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, tint, tintMode);
257b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
258b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            invalidateSelf();
259b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
260b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
261b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
262b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
263b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    protected boolean onStateChange(int[] stateSet) {
264b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        final VectorDrawableState state = mVectorState;
265b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        if (state.mTint != null && state.mTintMode != null) {
266b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
267b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            mVectorState.mVPathRenderer.setColorFilter(mTintFilter);
268b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette            return true;
269b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        }
270b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        return false;
271b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    }
272b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette
273b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette    @Override
274abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getOpacity() {
275abb7d134c02ac60091108c491dafb00877093170John Hoford        return PixelFormat.TRANSLUCENT;
276abb7d134c02ac60091108c491dafb00877093170John Hoford    }
277abb7d134c02ac60091108c491dafb00877093170John Hoford
278abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
279abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicWidth() {
280ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
281abb7d134c02ac60091108c491dafb00877093170John Hoford    }
282abb7d134c02ac60091108c491dafb00877093170John Hoford
283abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
284abb7d134c02ac60091108c491dafb00877093170John Hoford    public int getIntrinsicHeight() {
285ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
286abb7d134c02ac60091108c491dafb00877093170John Hoford    }
287abb7d134c02ac60091108c491dafb00877093170John Hoford
288abb7d134c02ac60091108c491dafb00877093170John Hoford    @Override
2899453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public boolean canApplyTheme() {
2909453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
2919453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
2929453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2939453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    @Override
2949453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    public void applyTheme(Theme t) {
2959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        super.applyTheme(t);
2969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
2979453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        final VectorDrawableState state = mVectorState;
298ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer path = state.mVPathRenderer;
2999453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        if (path != null && path.canApplyTheme()) {
3009453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            path.applyTheme(t);
3019453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
3029453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette    }
3039453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3044b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    /** @hide */
3054b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    public static VectorDrawable create(Resources resources, int rid) {
3064b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        try {
3074b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final XmlPullParser xpp = resources.getXml(rid);
3084b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final AttributeSet attrs = Xml.asAttributeSet(xpp);
3094b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
3104b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            factory.setNamespaceAware(true);
3114b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
3124b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            final VectorDrawable drawable = new VectorDrawable();
3134b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            drawable.inflate(resources, xpp, attrs);
3144b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
3154b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            return drawable;
3164b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (XmlPullParserException e) {
3174b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
3184b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        } catch (IOException e) {
3194b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette            Log.e(LOGTAG, "parser error", e);
3204b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        }
3214b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette        return null;
3224b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette    }
3234b1a7c203d5e32c8b2dc7f4f54f28559ca31860aAlan Viverette
3242af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    private static int applyAlpha(int color, float alpha) {
3252af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int alphaBytes = Color.alpha(color);
3262af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color &= 0x00FFFFFF;
3272af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
3282af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        return color;
3292af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui    }
3302af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
3319cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    @Override
3329cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
3339cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            throws XmlPullParserException, IOException {
3348d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final TypedArray a = obtainAttributes(res, theme, attrs, R.styleable.VectorDrawable);
3359cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        updateStateFromTypedArray(a);
3369cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        a.recycle();
3379cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3389cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
33955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        inflateInternal(res, parser, attrs, theme);
3409cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3419cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
3429cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mVPathRenderer.setColorFilter(mTintFilter);
3439cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
3449cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3459cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    private void updateStateFromTypedArray(TypedArray a) {
3469cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final VectorDrawableState state = mVectorState;
3479cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        // Account for any configuration changes.
3498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        state.mChangingConfigurations |= a.getChangingConfigurations();
3508e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
3519cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        // Extract the theme attributes, if any.
3529cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        state.mThemeAttrs = a.extractThemeAttrs();
3539cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3549cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final int tintMode = a.getInt(R.styleable.VectorDrawable_tintMode, -1);
3559cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tintMode != -1) {
3569cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
3579cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
3589cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
3599cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        final ColorStateList tint = a.getColorStateList(R.styleable.VectorDrawable_tint);
3609cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        if (tint != null) {
3619cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette            state.mTint = tint;
3629cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        }
363738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
364738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        state.mAutoMirrored = a.getBoolean(
365738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                R.styleable.VectorDrawable_autoMirrored, state.mAutoMirrored);
3669cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette    }
3679cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette
36855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
3698e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            Theme theme) throws XmlPullParserException, IOException {
3708e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        final VectorDrawableState state = mVectorState;
371ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
37255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        state.mVPathRenderer = pathRenderer;
3739453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
374abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noSizeTag = true;
375abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noViewportTag = true;
376abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean noPathTag = true;
3779453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
3784d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Use a stack to help to build the group tree.
3794d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // The top of the stack is always the current group.
3804d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
3814d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        groupStack.push(pathRenderer.mRootGroup);
382abb7d134c02ac60091108c491dafb00877093170John Hoford
383abb7d134c02ac60091108c491dafb00877093170John Hoford        int eventType = parser.getEventType();
384abb7d134c02ac60091108c491dafb00877093170John Hoford        while (eventType != XmlPullParser.END_DOCUMENT) {
385abb7d134c02ac60091108c491dafb00877093170John Hoford            if (eventType == XmlPullParser.START_TAG) {
3869453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                final String tagName = parser.getName();
3874d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final VGroup currentGroup = groupStack.peek();
3884d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
389abb7d134c02ac60091108c491dafb00877093170John Hoford                if (SHAPE_PATH.equals(tagName)) {
3909453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    final VPath path = new VPath();
3919453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                    path.inflate(res, attrs, theme);
3928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(path);
393e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (path.getPathName() != null) {
39455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
395e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
396abb7d134c02ac60091108c491dafb00877093170John Hoford                    noPathTag = false;
3978e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= path.mChangingConfigurations;
398abb7d134c02ac60091108c491dafb00877093170John Hoford                } else if (SHAPE_SIZE.equals(tagName)) {
399ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                    pathRenderer.parseSize(res, attrs);
400abb7d134c02ac60091108c491dafb00877093170John Hoford                    noSizeTag = false;
4018e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
402abb7d134c02ac60091108c491dafb00877093170John Hoford                } else if (SHAPE_VIEWPORT.equals(tagName)) {
403ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                    pathRenderer.parseViewport(res, attrs);
404abb7d134c02ac60091108c491dafb00877093170John Hoford                    noViewportTag = false;
4058e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= pathRenderer.mChangingConfigurations;
4066d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
4074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    VGroup newChildGroup = new VGroup();
4084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    newChildGroup.inflate(res, attrs, theme);
4098d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    currentGroup.mChildren.add(newChildGroup);
4104d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.push(newChildGroup);
411e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    if (newChildGroup.getGroupName() != null) {
41255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
41355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                                newChildGroup);
414e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                    }
4158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
416abb7d134c02ac60091108c491dafb00877093170John Hoford                }
4174d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
4184d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                final String tagName = parser.getName();
4194d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                if (SHAPE_GROUP.equals(tagName)) {
4204d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                    groupStack.pop();
4214d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
422abb7d134c02ac60091108c491dafb00877093170John Hoford            }
423abb7d134c02ac60091108c491dafb00877093170John Hoford            eventType = parser.next();
424abb7d134c02ac60091108c491dafb00877093170John Hoford        }
4259453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
4264d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the tree out for debug.
4274d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        if (DBG_VECTOR_DRAWABLE) {
4284d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
4296d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui        }
4306d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
43146e546c28fd52b4dedf0a0fbd313db589cb9048bztenghui        if (noSizeTag || noViewportTag || noPathTag) {
4329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final StringBuffer tag = new StringBuffer();
4339453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
434abb7d134c02ac60091108c491dafb00877093170John Hoford            if (noSizeTag) {
4359453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_SIZE);
436abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4379453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
438d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette            if (noViewportTag) {
439d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette                if (tag.length() > 0) {
440abb7d134c02ac60091108c491dafb00877093170John Hoford                    tag.append(" & ");
441abb7d134c02ac60091108c491dafb00877093170John Hoford                }
4429453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_SIZE);
443abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4449453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
445d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette            if (noPathTag) {
446d20974bd51852c71114b6e0e4ffdc3613a4d90aaAlan Viverette                if (tag.length() > 0) {
447abb7d134c02ac60091108c491dafb00877093170John Hoford                    tag.append(" or ");
448abb7d134c02ac60091108c491dafb00877093170John Hoford                }
4499453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette                tag.append(SHAPE_PATH);
450abb7d134c02ac60091108c491dafb00877093170John Hoford            }
4519453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
4529453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            throw new XmlPullParserException("no " + tag + " defined");
453abb7d134c02ac60091108c491dafb00877093170John Hoford        }
454abb7d134c02ac60091108c491dafb00877093170John Hoford    }
455abb7d134c02ac60091108c491dafb00877093170John Hoford
4564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
4574d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        String indent = "";
4588d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < level; i++) {
4594d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            indent += "    ";
4604d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
4614d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        // Print the current node
4628d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
4634d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                + " rotation is " + currentGroup.mRotate);
4648d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
4658d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        // Then print all the children groups
4668d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
4678d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            Object child = currentGroup.mChildren.get(i);
4688d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (child instanceof VGroup) {
4698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                printGroupTree((VGroup) child, level + 1);
4708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
4714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
4724d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui    }
4734d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
47455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    @Override
47555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    public int getChangingConfigurations() {
47655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        return super.getChangingConfigurations() | mVectorState.mChangingConfigurations;
47755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui    }
47855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
479482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    void setAllowCaching(boolean allowCaching) {
480482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        mAllowCaching = allowCaching;
481482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui    }
482482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
483738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    private boolean needMirroring() {
484738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
485738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
486738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
487738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
488738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public void setAutoMirrored(boolean mirrored) {
489738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        if (mVectorState.mAutoMirrored != mirrored) {
490738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            mVectorState.mAutoMirrored = mirrored;
491738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui            invalidateSelf();
492738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        }
493738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
494738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
495738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    @Override
496738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    public boolean isAutoMirrored() {
497738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        return mVectorState.mAutoMirrored;
498738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui    }
499738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui
5005c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    private static class VectorDrawableState extends ConstantState {
5019cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette        int[] mThemeAttrs;
5025c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        int mChangingConfigurations;
503ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        VPathRenderer mVPathRenderer;
504b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        ColorStateList mTint;
505b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette        Mode mTintMode;
506738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui        boolean mAutoMirrored;
5075c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
508482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Bitmap mCachedBitmap;
509482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int[] mCachedThemeAttrs;
510482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        ColorStateList mCachedTint;
511482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        Mode mCachedTintMode;
512482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        int mCachedRootAlpha;
513482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
51455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Deep copy for mutate() or implicitly mutate.
5155c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public VectorDrawableState(VectorDrawableState copy) {
5165c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            if (copy != null) {
5179cd14fc710cf81cc6d1c47d599abe349d3aa87dcAlan Viverette                mThemeAttrs = copy.mThemeAttrs;
5185c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette                mChangingConfigurations = copy.mChangingConfigurations;
519ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
520b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTint = copy.mTint;
521b3c56086d802ae28888dd97ba1f49bd6cee0b673Alan Viverette                mTintMode = copy.mTintMode;
522738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                mAutoMirrored = copy.mAutoMirrored;
5235c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            }
5245c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
5255c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
526482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        public boolean canReuseCache(int width, int height) {
527482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            if (mCachedThemeAttrs == mThemeAttrs
528482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTint == mTint
529482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedTintMode == mTintMode
530738177caf6a755a59ca6b17bb968be0aa4e8e10fztenghui                    && mAutoMirrored == mAutoMirrored
531482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && width == mCachedBitmap.getWidth()
532482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && height == mCachedBitmap.getHeight()
533482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha())  {
534482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui                return true;
535482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            }
536482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            return false;
537482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
538482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
539482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        public void updateCacheStates() {
540482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
541482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            // likely hit cache miss more, but practically not much difference.
542482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedThemeAttrs = mThemeAttrs;
543482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTint = mTint;
544482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedTintMode = mTintMode;
545482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
546482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui        }
547482eb53c8a7d5180a2d0ce3b0a779c18960aa8cdztenghui
54855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VectorDrawableState() {
54955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mVPathRenderer = new VPathRenderer();
55055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
55155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
5525c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
5535c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable() {
5545c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, null, null);
5555c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
5565c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
5575c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
5585c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res) {
5595c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, res, null);
5605c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
5615c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
5625c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
5635c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public Drawable newDrawable(Resources res, Theme theme) {
5645c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return new VectorDrawable(this, res, theme);
5655c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
5665c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
5675c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        @Override
5685c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        public int getChangingConfigurations() {
5695c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette            return mChangingConfigurations;
5705c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette        }
5715c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette    }
5725c981a100ef30d2925588b69f8b9fe349ee5bfdeAlan Viverette
573ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui    private static class VPathRenderer {
5744d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        /* Right now the internal data structure is organized as a tree.
5754d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * Each node can be a group node, or a path.
5764d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * A group node can have groups or paths as children, but a path node has
5774d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * no children.
5784d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         * One example can be:
5794d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                 Root Group
5804d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *                /    |     \
5814d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *           Group    Path    Group
5824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *          /     \             |
5834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *         Path   Path         Path
5844d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         *
5854d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui         */
58655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables that only used temporarily inside the draw() call, so there
58755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // is no need for deep copying.
5884b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private final Path mPath = new Path();
5894b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private final Path mRenderPath = new Path();
5904d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
59155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mFinalPathMatrix = new Matrix();
5924b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
5934b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mStrokePaint;
5944b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        private Paint mFillPaint;
595fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        private ColorFilter mColorFilter;
596abb7d134c02ac60091108c491dafb00877093170John Hoford        private PathMeasure mPathMeasure;
5974b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
59855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
59955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
6008e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
60155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final VGroup mRootGroup;
6024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mBaseWidth = 0;
6034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mBaseHeight = 0;
6044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mViewportWidth = 0;
6054d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private float mViewportHeight = 0;
6062af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        private int mRootAlpha = 0xFF;
6079453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
60855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
609abb7d134c02ac60091108c491dafb00877093170John Hoford
610ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer() {
6114d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mRootGroup = new VGroup();
612abb7d134c02ac60091108c491dafb00877093170John Hoford        }
6139453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6142af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public void setRootAlpha(int alpha) {
6152af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mRootAlpha = alpha;
6162af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
6172af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
6182af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        public int getRootAlpha() {
6192af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            return mRootAlpha;
6202af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        }
6212af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui
622ddbbb8ae8561c9e61becd03faa40997d76ab5a51ztenghui        public VPathRenderer(VPathRenderer copy) {
62355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
624abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseWidth = copy.mBaseWidth;
625abb7d134c02ac60091108c491dafb00877093170John Hoford            mBaseHeight = copy.mBaseHeight;
626abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportWidth = copy.mViewportHeight;
627abb7d134c02ac60091108c491dafb00877093170John Hoford            mViewportHeight = copy.mViewportHeight;
6288e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations = copy.mChangingConfigurations;
62955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRootAlpha = copy.mRootAlpha;
630abb7d134c02ac60091108c491dafb00877093170John Hoford        }
631abb7d134c02ac60091108c491dafb00877093170John Hoford
6329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public boolean canApplyTheme() {
6334d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // If one of the paths can apply theme, then return true;
6344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return recursiveCanApplyTheme(mRootGroup);
6354d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
6364d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
6374d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private boolean recursiveCanApplyTheme(VGroup currentGroup) {
6384d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, if there is one path return true,
6394d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // then we return true for the whole tree.
6408d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
6418d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
6428d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
6438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
6448d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
6458d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
6468d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()
6478d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            || recursiveCanApplyTheme(childGroup)) {
6488d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
6498d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
6508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
6518d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
6528d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
6538d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        return true;
6548d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
6554d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
6564d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
6579453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            return false;
6589453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
6599453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
6609453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void applyTheme(Theme t) {
6614d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Apply theme to every path of the tree.
6624d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            recursiveApplyTheme(mRootGroup, t);
6634d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
6644d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
6654d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
6664d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // We can do a tree traverse here, apply theme to all paths which
6674d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // can apply theme.
6688d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = currentGroup.mChildren;
6698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
6708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = children.get(i);
6718d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
6728d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
6738d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childGroup.canApplyTheme()) {
6748d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childGroup.applyTheme(t);
6758d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
6768d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    recursiveApplyTheme(childGroup, t);
6778d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
6788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
6798d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (childPath.canApplyTheme()) {
6808d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        childPath.applyTheme(t);
6818d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
6824d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui                }
6834d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
684abb7d134c02ac60091108c491dafb00877093170John Hoford        }
685abb7d134c02ac60091108c491dafb00877093170John Hoford
686fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        public void setColorFilter(ColorFilter colorFilter) {
687fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mColorFilter = colorFilter;
688fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
689fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mFillPaint != null) {
690fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                mFillPaint.setColorFilter(colorFilter);
691fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            }
692fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
693fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mStrokePaint != null) {
694fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                mStrokePaint.setColorFilter(colorFilter);
695fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            }
6966d9c422de5e0a3890dd723cb1b9264d4507053e9ztenghui
697fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette        }
698fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
6994d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
7002af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                float currentAlpha, Canvas canvas, int w, int h) {
7014d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Calculate current group's matrix by preConcat the parent's and
7024d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // and the current one on the top of the stack.
7034d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
7044d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Mi the local matrix at level i of the group tree.
7054d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
7064d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
7074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
7084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
7092af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            float stackedAlpha = currentAlpha * currentGroup.mGroupAlpha;
7108d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
7118d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            // Draw the group tree in the same order as the XML file.
7128d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
7138d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object child = currentGroup.mChildren.get(i);
7148d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (child instanceof VGroup) {
7158d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup childGroup = (VGroup) child;
7168d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
7178d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                            stackedAlpha, canvas, w, h);
7188d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (child instanceof VPath) {
7198d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath childPath = (VPath) child;
7208d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    drawPath(currentGroup, childPath, stackedAlpha, canvas, w, h);
7218d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
722abb7d134c02ac60091108c491dafb00877093170John Hoford            }
7234d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
724abb7d134c02ac60091108c491dafb00877093170John Hoford
7254d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public void draw(Canvas canvas, int w, int h) {
7264d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // Travese the tree in pre-order to draw.
7272af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, ((float) mRootAlpha) / 0xFF, canvas, w, h);
728abb7d134c02ac60091108c491dafb00877093170John Hoford        }
729abb7d134c02ac60091108c491dafb00877093170John Hoford
7308d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        private void drawPath(VGroup vGroup, VPath vPath, float stackedAlpha,
7318d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Canvas canvas, int w, int h) {
7329453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
733abb7d134c02ac60091108c491dafb00877093170John Hoford
7344d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mFinalPathMatrix.set(vGroup.mStackedMatrix);
7354d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mFinalPathMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
7368e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mFinalPathMatrix.postTranslate(
7378e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
738abb7d134c02ac60091108c491dafb00877093170John Hoford
7398d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            vPath.toPath(mPath);
7408d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final Path path = mPath;
741abb7d134c02ac60091108c491dafb00877093170John Hoford
7428d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
7438d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
7448d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float end = (vPath.mTrimPathEnd + vPath.mTrimPathOffset) % 1.0f;
7459453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
7468d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (mPathMeasure == null) {
7478d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure = new PathMeasure();
7484b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette                }
7498d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                mPathMeasure.setPath(mPath, false);
7508d0d24f7a2b1a59060aa18926984491691d3c667ztenghui
7518d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                float len = mPathMeasure.getLength();
7528d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                start = start * len;
7538d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                end = end * len;
7548d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                path.reset();
7558d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (start > end) {
7568d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(start, len, path, true);
7578d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(0f, end, path, true);
7588d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else {
7598d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mPathMeasure.getSegment(start, end, path, true);
7608d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
7618d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                path.rLineTo(0, 0); // fix bug in measure
7628d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            }
7634b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
7648d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.reset();
7659453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
7668d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            mRenderPath.addPath(path, mFinalPathMatrix);
7674b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
7688d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            if (vPath.mClip) {
7698d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                canvas.clipPath(mRenderPath, Region.Op.REPLACE);
7708d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            } else {
7718d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (vPath.mFillColor != 0) {
7728d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mFillPaint == null) {
7738d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint = new Paint();
7748d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setColorFilter(mColorFilter);
7758d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
7768d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mFillPaint.setAntiAlias(true);
77763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                    }
7788d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mFillPaint.setColor(applyAlpha(vPath.mFillColor, stackedAlpha));
7798d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, mFillPaint);
7808d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                }
78163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
7828d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (vPath.mStrokeColor != 0) {
7838d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (mStrokePaint == null) {
7848d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint = new Paint();
7858d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setColorFilter(mColorFilter);
7868d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
7878d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        mStrokePaint.setAntiAlias(true);
7888d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
7894b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
7908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    final Paint strokePaint = mStrokePaint;
7918d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (vPath.mStrokeLineJoin != null) {
7928d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
7938d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
794abb7d134c02ac60091108c491dafb00877093170John Hoford
7958d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (vPath.mStrokeLineCap != null) {
7968d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        strokePaint.setStrokeCap(vPath.mStrokeLineCap);
7978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
79863cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
7998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
80063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
8018d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setColor(applyAlpha(vPath.mStrokeColor, stackedAlpha));
8028d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
8038d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
80463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui                }
805abb7d134c02ac60091108c491dafb00877093170John Hoford            }
806abb7d134c02ac60091108c491dafb00877093170John Hoford        }
807abb7d134c02ac60091108c491dafb00877093170John Hoford
808abb7d134c02ac60091108c491dafb00877093170John Hoford        private void parseViewport(Resources r, AttributeSet attrs)
809abb7d134c02ac60091108c491dafb00877093170John Hoford                throws XmlPullParserException {
8104b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
8118e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
8128e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
8138e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
8148e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
8158e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mViewportWidth = a.getFloat(
8168e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableViewport_viewportWidth, mViewportWidth);
8178e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mViewportHeight = a.getFloat(
8188e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableViewport_viewportHeight, mViewportHeight);
819fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
820fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mViewportWidth <= 0) {
821fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
822fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<viewport> tag requires viewportWidth > 0");
823fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            } else if (mViewportHeight <= 0) {
824fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
825fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<viewport> tag requires viewportHeight > 0");
826abb7d134c02ac60091108c491dafb00877093170John Hoford            }
827fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
828abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
829abb7d134c02ac60091108c491dafb00877093170John Hoford        }
830abb7d134c02ac60091108c491dafb00877093170John Hoford
831abb7d134c02ac60091108c491dafb00877093170John Hoford        private void parseSize(Resources r, AttributeSet attrs)
8328d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                throws XmlPullParserException {
8334b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
8348e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
8358e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
8368e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
8378e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
838fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, mBaseWidth);
839fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, mBaseHeight);
840fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
841fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            if (mBaseWidth <= 0) {
842fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
843fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<size> tag requires width > 0");
844fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette            } else if (mBaseHeight <= 0) {
845fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                throw new XmlPullParserException(a.getPositionDescription() +
846fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette                        "<size> tag requires height > 0");
847abb7d134c02ac60091108c491dafb00877093170John Hoford            }
848fd6e411767735478ee0f69ba01d77def4c6b2627Alan Viverette
849abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
850abb7d134c02ac60091108c491dafb00877093170John Hoford        }
8514b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette
852abb7d134c02ac60091108c491dafb00877093170John Hoford    }
853abb7d134c02ac60091108c491dafb00877093170John Hoford
854e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui    static class VGroup {
85555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
85655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // the parents' local matrices with the current one.
85755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private final Matrix mStackedMatrix = new Matrix();
85855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
85955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
86055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
8618d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
862abb7d134c02ac60091108c491dafb00877093170John Hoford
86363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mRotate = 0;
86463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotX = 0;
86563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private float mPivotY = 0;
866452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleX = 1;
867452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mScaleY = 1;
868452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateX = 0;
869452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui        private float mTranslateY = 0;
8702af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        private float mGroupAlpha = 1;
8714d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
87255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // mLocalMatrix is updated based on the update of transformation information,
87355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // either parsed from the XML or by animation.
8744d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private final Matrix mLocalMatrix = new Matrix();
8758e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private int mChangingConfigurations;
87663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        private int[] mThemeAttrs;
877e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        private String mGroupName = null;
878e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
87955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
88055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mRotate = copy.mRotate;
88155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotX = copy.mPivotX;
88255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPivotY = copy.mPivotY;
88355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleX = copy.mScaleX;
88455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mScaleY = copy.mScaleY;
88555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateX = copy.mTranslateX;
88655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTranslateY = copy.mTranslateY;
88755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupAlpha = copy.mGroupAlpha;
88855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
88955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mGroupName = copy.mGroupName;
89055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
89155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mGroupName != null) {
89255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                targetsMap.put(mGroupName, this);
89355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
89455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
89555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mLocalMatrix.set(copy.mLocalMatrix);
89655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
8978d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            final ArrayList<Object> children = copy.mChildren;
8988d0d24f7a2b1a59060aa18926984491691d3c667ztenghui            for (int i = 0; i < children.size(); i++) {
8998d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                Object copyChild = children.get(i);
9008d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                if (copyChild instanceof VGroup) {
9018d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VGroup copyGroup = (VGroup) copyChild;
9028d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
9038d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                } else if (copyChild instanceof VPath) {
9048d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath copyPath = (VPath) copyChild;
9058d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    VPath newPath = new VPath(copyPath);
9068d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    mChildren.add(newPath);
9078d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    if (newPath.mPathName != null) {
9088d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                        targetsMap.put(newPath.mPathName, newPath);
9098d0d24f7a2b1a59060aa18926984491691d3c667ztenghui                    }
91055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                }
91155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            }
91255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
91355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
91455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VGroup() {
91555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
91655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
917e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        /* Getter and Setter */
918e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getRotation() {
919e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mRotate;
920e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
921e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
922e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setRotation(float rotation) {
923e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (rotation != mRotate) {
924e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mRotate = rotation;
925e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
926e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
927e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
928e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
929e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotX() {
930e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotX;
931e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
932e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
933e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotX(float pivotX) {
934e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotX != mPivotX) {
935e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotX = pivotX;
936e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
937e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
938e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
939e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
940e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getPivotY() {
941e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPivotY;
942e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
943e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
944e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setPivotY(float pivotY) {
945e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (pivotY != mPivotY) {
946e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mPivotY = pivotY;
947e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
948e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
949e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
950e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
951e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleX() {
952e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleX;
953e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
9544d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
955e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleX(float scaleX) {
956e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleX != mScaleX) {
957e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleX = scaleX;
958e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
959e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
960e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
961e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
962e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getScaleY() {
963e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mScaleY;
964e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
965e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
966e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setScaleY(float scaleY) {
967e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (scaleY != mScaleY) {
968e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mScaleY = scaleY;
969e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
970e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
971e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
972e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
973e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateX() {
974e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateX;
975e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
976e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
977e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateX(float translateX) {
978e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateX != mTranslateX) {
979e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateX = translateX;
980e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
981e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
982e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
983e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
984e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getTranslateY() {
985e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTranslateY;
986e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
987e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
988e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setTranslateY(float translateY) {
989e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (translateY != mTranslateY) {
990e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mTranslateY = translateY;
991e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                updateLocalMatrix();
992e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
993e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
994e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
995e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public float getAlpha() {
996e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mGroupAlpha;
997e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
998e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
999e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public void setAlpha(float groupAlpha) {
1000e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            if (groupAlpha != mGroupAlpha) {
1001e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui                mGroupAlpha = groupAlpha;
1002e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            }
1003e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1004e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1005e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public String getGroupName() {
1006e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mGroupName;
10074d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
10084d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10094d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public Matrix getLocalMatrix() {
10104d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return mLocalMatrix;
10114d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
10124d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10134d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        public boolean canApplyTheme() {
10144d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            return mThemeAttrs != null;
10154d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
10164d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10178e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void inflate(Resources res, AttributeSet attrs, Theme theme) {
10188e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = obtainAttributes(res, theme, attrs,
10198e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawableGroup);
10208e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
10218e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            a.recycle();
10228e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
10238e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
10248e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private void updateStateFromTypedArray(TypedArray a) {
10258e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
10268e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
102763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
10288e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Extract the theme attributes, if any.
10298e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mThemeAttrs = a.extractThemeAttrs();
103063cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
103163cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mRotate = a.getFloat(R.styleable.VectorDrawableGroup_rotation, mRotate);
103263cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mPivotX = a.getFloat(R.styleable.VectorDrawableGroup_pivotX, mPivotX);
103363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            mPivotY = a.getFloat(R.styleable.VectorDrawableGroup_pivotY, mPivotY);
1034452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mScaleX = a.getFloat(R.styleable.VectorDrawableGroup_scaleX, mScaleX);
1035452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
1036452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
1037452f6ece7fe2fd1a85fca53f54e90bf041083b21ztenghui            mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
10382af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui            mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
103963cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
10408e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final String groupName = a.getString(R.styleable.VectorDrawableGroup_name);
10418e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (groupName != null) {
10428e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                mGroupName = groupName;
104363cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            }
104463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
10458e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateLocalMatrix();
10468e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
10474d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10488e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void applyTheme(Theme t) {
10498e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (mThemeAttrs == null) {
10508e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                return;
10514d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            }
10524d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui
10538e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
10548e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
105563cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
105663cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui        }
105763cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui
10584d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        private void updateLocalMatrix() {
10594d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // The order we apply is the same as the
10604d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
10614d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.reset();
10624d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
10634d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
10644d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
10654d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
10664d24caf1dec2babf273b18c99638fe2a0635ced4ztenghui        }
1067abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1068abb7d134c02ac60091108c491dafb00877093170John Hoford
1069cf4832f69c8786b098ce18c24319021f8cd6733aztenghui    private static class VPath {
107055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        /////////////////////////////////////////////////////
107155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
10729453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private int[] mThemeAttrs;
10739453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1074abb7d134c02ac60091108c491dafb00877093170John Hoford        int mStrokeColor = 0;
1075abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeWidth = 0;
1076abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeOpacity = Float.NaN;
10772af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui        int mFillColor = Color.BLACK;
1078abb7d134c02ac60091108c491dafb00877093170John Hoford        int mFillRule;
1079abb7d134c02ac60091108c491dafb00877093170John Hoford        float mFillOpacity = Float.NaN;
1080abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathStart = 0;
1081abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathEnd = 1;
1082abb7d134c02ac60091108c491dafb00877093170John Hoford        float mTrimPathOffset = 0;
10839453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
1084abb7d134c02ac60091108c491dafb00877093170John Hoford        boolean mClip = false;
10854b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
10864b3988d159e1c9faa2a7e16c9aca9951264bb429Alan Viverette        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
1087abb7d134c02ac60091108c491dafb00877093170John Hoford        float mStrokeMiterlimit = 4;
10889453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
108955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private PathParser.PathDataNode[] mNodes = null;
10908d0d24f7a2b1a59060aa18926984491691d3c667ztenghui        String mPathName;
109155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        private int mChangingConfigurations;
1092abb7d134c02ac60091108c491dafb00877093170John Hoford
10939453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public VPath() {
10949453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            // Empty constructor.
10959453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
10969453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
109755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public VPath(VPath copy) {
109855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mThemeAttrs = copy.mThemeAttrs;
109955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
110055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeColor = copy.mStrokeColor;
110155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeWidth = copy.mStrokeWidth;
110255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeOpacity = copy.mStrokeOpacity;
110355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillColor = copy.mFillColor;
110455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillRule = copy.mFillRule;
110555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mFillOpacity = copy.mFillOpacity;
110655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathStart = copy.mTrimPathStart;
110755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathEnd = copy.mTrimPathEnd;
110855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mTrimPathOffset = copy.mTrimPathOffset;
110955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
111055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mClip = copy.mClip;
111155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineCap = copy.mStrokeLineCap;
111255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
111355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
111455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
111555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
111655f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mPathName = copy.mPathName;
111755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mChangingConfigurations = copy.mChangingConfigurations;
111855f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        }
111955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
1120abb7d134c02ac60091108c491dafb00877093170John Hoford        public void toPath(Path path) {
1121abb7d134c02ac60091108c491dafb00877093170John Hoford            path.reset();
112255f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (mNodes != null) {
112355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
1124abb7d134c02ac60091108c491dafb00877093170John Hoford            }
1125abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1126abb7d134c02ac60091108c491dafb00877093170John Hoford
1127e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        public String getPathName() {
1128e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mPathName;
1129abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1130abb7d134c02ac60091108c491dafb00877093170John Hoford
11317f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
11327f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
11337f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_BUTT:
11347f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.BUTT;
11357f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_ROUND:
11367f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.ROUND;
11377f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINECAP_SQUARE:
11387f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Cap.SQUARE;
11397f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
11407f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
11417f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
11427f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
11437f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
11447f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
11457f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            switch (id) {
11467f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_MITER:
11477f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.MITER;
11487f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_ROUND:
11497f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.ROUND;
11507f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                case LINEJOIN_BEVEL:
11517f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return Paint.Join.BEVEL;
11527f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                default:
11537f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    return defValue;
11547f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            }
11557f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette        }
11567f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette
1157eb034fbca40006c55db143047eb628c4b657730aztenghui        /* Setters and Getters, mostly used by animator from AnimatedVectorDrawable. */
1158eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1159eb034fbca40006c55db143047eb628c4b657730aztenghui        public PathParser.PathDataNode[] getPathData() {
116055f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            return mNodes;
1161eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1162eb034fbca40006c55db143047eb628c4b657730aztenghui
1163eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
116455f765441c6cec6b2990de12f68d1c4ac444d35cztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
116555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
1166eb034fbca40006c55db143047eb628c4b657730aztenghui                // This should not happen in the middle of animation.
116755f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                mNodes = PathParser.deepCopyNodes(nodes);
1168eb034fbca40006c55db143047eb628c4b657730aztenghui            } else {
116955f765441c6cec6b2990de12f68d1c4ac444d35cztenghui                PathParser.updateNodes(mNodes, nodes);
1170eb034fbca40006c55db143047eb628c4b657730aztenghui            }
1171eb034fbca40006c55db143047eb628c4b657730aztenghui        }
1172eb034fbca40006c55db143047eb628c4b657730aztenghui
1173eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1174e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int getStroke() {
1175e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeColor;
1176e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1177e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1178eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1179e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStroke(int strokeColor) {
1180e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeColor = strokeColor;
1181e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1182e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1183eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1184e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeWidth() {
1185e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeWidth;
1186e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1187e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1188eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1189e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeWidth(float strokeWidth) {
1190e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeWidth = strokeWidth;
1191e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1192e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1193eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1194e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getStrokeOpacity() {
1195e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mStrokeOpacity;
1196e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1197e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1198eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1199e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setStrokeOpacity(float strokeOpacity) {
1200e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mStrokeOpacity = strokeOpacity;
1201e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1202e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1203eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1204e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        int getFill() {
1205e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillColor;
1206e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1207e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1208eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1209e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setFill(int fillColor) {
1210e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillColor = fillColor;
1211e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1212e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1213eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1214e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getFillOpacity() {
1215e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mFillOpacity;
1216e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1217e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1218eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1219e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setFillOpacity(float fillOpacity) {
1220e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mFillOpacity = fillOpacity;
1221e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1222e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1223eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1224e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathStart() {
1225e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathStart;
1226e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1227e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1228eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1229e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathStart(float trimPathStart) {
1230e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathStart = trimPathStart;
1231e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1232e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1233eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1234e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathEnd() {
1235e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathEnd;
1236e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1237e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1238eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1239e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathEnd(float trimPathEnd) {
1240e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathEnd = trimPathEnd;
1241e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1242e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1243eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1244e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        float getTrimPathOffset() {
1245e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            return mTrimPathOffset;
1246e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1247e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
1248eb034fbca40006c55db143047eb628c4b657730aztenghui        @SuppressWarnings("unused")
1249e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        void setTrimPathOffset(float trimPathOffset) {
1250e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui            mTrimPathOffset = trimPathOffset;
1251e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui        }
1252e5e92602a41a4ddc7b42cd1c171a0edfbd09b8daztenghui
12538e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public boolean canApplyTheme() {
12548e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            return mThemeAttrs != null;
12558e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
12568e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
12579453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        public void inflate(Resources r, AttributeSet attrs, Theme theme) {
12589453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.VectorDrawablePath);
12598e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
1260abb7d134c02ac60091108c491dafb00877093170John Hoford            a.recycle();
1261abb7d134c02ac60091108c491dafb00877093170John Hoford        }
1262abb7d134c02ac60091108c491dafb00877093170John Hoford
12638e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        private void updateStateFromTypedArray(TypedArray a) {
12648e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Account for any configuration changes.
12658e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mChangingConfigurations |= a.getChangingConfigurations();
12669453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12678e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            // Extract the theme attributes, if any.
12688e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mThemeAttrs = a.extractThemeAttrs();
12699453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12707f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mClip = a.getBoolean(R.styleable.VectorDrawablePath_clipToPath, mClip);
127155f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
12728e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            mPathName = a.getString(R.styleable.VectorDrawablePath_name);
127355f765441c6cec6b2990de12f68d1c4ac444d35cztenghui            mNodes = PathParser.createNodesFromPathData(a.getString(
12748e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                    R.styleable.VectorDrawablePath_pathData));
127555f765441c6cec6b2990de12f68d1c4ac444d35cztenghui
12767f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mFillColor = a.getColor(R.styleable.VectorDrawablePath_fill, mFillColor);
12777f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mFillOpacity = a.getFloat(R.styleable.VectorDrawablePath_fillOpacity, mFillOpacity);
12787f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeLineCap = getStrokeLineCap(a.getInt(
12797f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeLineCap, -1), mStrokeLineCap);
12807f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeLineJoin = getStrokeLineJoin(a.getInt(
12817f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeLineJoin, -1), mStrokeLineJoin);
12827f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeMiterlimit = a.getFloat(
12837f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeMiterLimit, mStrokeMiterlimit);
12847f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeColor = a.getColor(R.styleable.VectorDrawablePath_stroke, mStrokeColor);
12857f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeOpacity = a.getFloat(
12867f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_strokeOpacity, mStrokeOpacity);
12877f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mStrokeWidth = a.getFloat(R.styleable.VectorDrawablePath_strokeWidth, mStrokeWidth);
12887f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathEnd = a.getFloat(R.styleable.VectorDrawablePath_trimPathEnd, mTrimPathEnd);
12897f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathOffset = a.getFloat(
12907f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_trimPathOffset, mTrimPathOffset);
12917f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette            mTrimPathStart = a.getFloat(
12927f1ab7a43fd7e65bbd7460334014ecc73dbb1b8dAlan Viverette                    R.styleable.VectorDrawablePath_trimPathStart, mTrimPathStart);
12939453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
12949453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            updateColorAlphas();
12958e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        }
12968e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
12978e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette        public void applyTheme(Theme t) {
12988e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            if (mThemeAttrs == null) {
12998e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette                return;
13008e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            }
13018e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette
13028e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            final TypedArray a = t.resolveAttributes(mThemeAttrs, R.styleable.VectorDrawablePath);
13038e5e11b99fac942122ee2d6cdd30af51564861aeAlan Viverette            updateStateFromTypedArray(a);
130463cfd85bcce488a3f3952bd1db523a727d30ca39ztenghui            a.recycle();
13059453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
13069453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
13079453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        private void updateColorAlphas() {
13089453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            if (!Float.isNaN(mFillOpacity)) {
13092af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                mFillColor = applyAlpha(mFillColor, mFillOpacity);
13109453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            }
13119453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette
13129453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            if (!Float.isNaN(mStrokeOpacity)) {
13132af745b56cf4bdfdd9c05d90a4ccc740bf77a4feztenghui                mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity);
13149453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette            }
13159453b7cfd4bbb35467bd7f947f850bd154982fceAlan Viverette        }
1316abb7d134c02ac60091108c491dafb00877093170John Hoford    }
1317abb7d134c02ac60091108c491dafb00877093170John Hoford}
1318