VectorDrawableCompat.java revision c39d9c75590eca86a5e7e32a8824ba04a0d42e9b
14fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/*
24fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Copyright (C) 2015 The Android Open Source Project
34fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
44fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
54fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * in compliance with the License. You may obtain a copy of the License at
64fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
74fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * http://www.apache.org/licenses/LICENSE-2.0
84fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui *
94fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * Unless required by applicable law or agreed to in writing, software distributed under the License
104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * or implied. See the License for the specific language governing permissions and limitations under
124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui * the License.
134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuipackage android.support.graphics.drawable;
164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport android.support.annotation.RestrictTo;
18ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport android.support.v4.content.res.ResourcesCompat;
19ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhuimport android.support.v4.graphics.drawable.DrawableCompat;
20e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banesimport org.xmlpull.v1.XmlPullParser;
21e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banesimport org.xmlpull.v1.XmlPullParserException;
22e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.annotation.TargetApi;
244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.ColorStateList;
254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources;
264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.Resources.Theme;
274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.content.res.TypedArray;
284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Bitmap;
294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Canvas;
304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Color;
314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.ColorFilter;
324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Matrix;
334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Paint;
344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Path;
354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PathMeasure;
364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PixelFormat;
374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff;
384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuff.Mode;
394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.PorterDuffColorFilter;
404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Rect;
414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.Region;
424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.graphics.drawable.Drawable;
439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.graphics.drawable.VectorDrawable;
449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhuimport android.os.Build;
45968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhuimport android.support.annotation.DrawableRes;
464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.NonNull;
474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.annotation.Nullable;
484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.support.v4.util.ArrayMap;
494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.AttributeSet;
504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Log;
514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport android.util.Xml;
524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.io.IOException;
544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.ArrayList;
554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghuiimport java.util.Stack;
564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
57c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viveretteimport static android.support.annotation.RestrictTo.Scope.GROUP_ID;
58c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette
594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui/**
60c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu * For API 24 and above, this class is delegating to the framework's {@link VectorDrawable}.
61ab9d2bf6fe28ff4a95985526daa128239c03d821Teng-Hui Zhu * For older API version, this class lets you create a drawable based on an XML vector graphic.
627c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * <p>
637c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * VectorDrawableCompat are defined in the same XML format as {@link VectorDrawable}.
647c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * </p>
657c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * You can always create a VectorDrawableCompat object and use it as a Drawable by the Java API.
667c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * In order to refer to VectorDrawableCompat inside a XML file,  you can use app:srcCompat attribute
677c839dcff721b584defb5bedb18c05fae5b99d24Teng-Hui Zhu * in AppCompat library's ImageButton or ImageView.
684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui */
699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu@TargetApi(Build.VERSION_CODES.LOLLIPOP)
70968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhupublic class VectorDrawableCompat extends VectorDrawableCommon {
714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final String LOGTAG = "VectorDrawableCompat";
724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    static final PorterDuff.Mode DEFAULT_TINT_MODE = PorterDuff.Mode.SRC_IN;
744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_CLIP_PATH = "clip-path";
764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_GROUP = "group";
774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_PATH = "path";
784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final String SHAPE_VECTOR = "vector";
794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_BUTT = 0;
814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_ROUND = 1;
824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINECAP_SQUARE = 2;
834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_MITER = 0;
854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_ROUND = 1;
864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static final int LINEJOIN_BEVEL = 2;
874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
881f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Cap the bitmap size, such that it won't hurt the performance too much
891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // and it won't crash due to a very large scale.
901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // The drawable will look blurry above this size.
911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private static final int MAX_CACHED_BITMAP_SIZE = 2048;
921f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
93d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    private static final boolean DBG_VECTOR_DRAWABLE = false;
944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private VectorDrawableCompatState mVectorState;
964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private PorterDuffColorFilter mTintFilter;
984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private ColorFilter mColorFilter;
994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mMutated;
1014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // AnimatedVectorDrawable needs to turn off the cache all the time, otherwise,
1034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // caching the bitmap by default is allowed.
1044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean mAllowCaching = true;
1054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // The Constant state associated with the <code>mDelegateDrawable</code>.
1079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private ConstantState mCachedConstantStateDelegate;
1089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
1091f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    // Temp variable, only for saving "new" operation at the draw() time.
1101f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final float[] mTmpFloats = new float[9];
1111f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Matrix mTmpMatrix = new Matrix();
1121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu    private final Rect mTmpBounds = new Rect();
1131f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1148fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat() {
1159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        mVectorState = new VectorDrawableCompatState();
1164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
1174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1188fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    VectorDrawableCompat(@NonNull VectorDrawableCompatState state) {
1194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState = state;
1204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
1214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
1224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
1244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public Drawable mutate() {
1259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
1269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.mutate();
1279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return this;
1289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
1299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
1304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mMutated && super.mutate() == this) {
1319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mVectorState = new VectorDrawableCompatState(mVectorState);
1324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mMutated = true;
1334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
1344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return this;
1354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
1364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    Object getTargetByName(String name) {
1384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.mVGTargetsMap.get(name);
1394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
1404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
1424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public ConstantState getConstantState() {
1439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
1442c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Such that the configuration can be refreshed.
1452c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return new VectorDrawableDelegateState(mDelegateDrawable.getConstantState());
1469f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
1474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mVectorState.mChangingConfigurations = getChangingConfigurations();
1484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState;
1494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
1504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
1524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void draw(Canvas canvas) {
1539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
1549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.draw(canvas);
1559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
1569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
1571f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // We will offset the bounds for drawBitmap, so copyBounds() here instead
1581f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // of getBounds().
1591f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        copyBounds(mTmpBounds);
1601f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (mTmpBounds.width() <= 0 || mTmpBounds.height() <= 0) {
1611f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            // Nothing to draw
1621f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            return;
1631f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
1649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
1651f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Color filters always override tint filters.
1661f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final ColorFilter colorFilter = (mColorFilter == null ? mTintFilter : mColorFilter);
1671f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1681f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // The imageView can scale the canvas in different ways, in order to
1691f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // avoid blurry scaling, we have to draw into a bitmap with exact pixel
1701f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // size first. This bitmap size is determined by the bounds and the
1711f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // canvas scale.
1721f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.getMatrix(mTmpMatrix);
1731f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpMatrix.getValues(mTmpFloats);
1741f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleX = Math.abs(mTmpFloats[Matrix.MSCALE_X]);
1751f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasScaleY = Math.abs(mTmpFloats[Matrix.MSCALE_Y]);
1761f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1771f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewX = Math.abs(mTmpFloats[Matrix.MSKEW_X]);
1781f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        float canvasSkewY = Math.abs(mTmpFloats[Matrix.MSKEW_Y]);
1791f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1801f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // When there is any rotation / skew, then the scale value is not valid.
1811f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (canvasSkewX != 0 || canvasSkewY != 0) {
1821f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleX = 1.0f;
1831f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvasScaleY = 1.0f;
1841f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        }
1851f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1861f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledWidth = (int) (mTmpBounds.width() * canvasScaleX);
1871f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        int scaledHeight = (int) (mTmpBounds.height() * canvasScaleY);
1881f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledWidth = Math.min(MAX_CACHED_BITMAP_SIZE, scaledWidth);
1891f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        scaledHeight = Math.min(MAX_CACHED_BITMAP_SIZE, scaledHeight);
1901f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu
1911f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        if (scaledWidth <= 0 || scaledHeight <= 0) {
1924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return;
1934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
1944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int saveCount = canvas.save();
1961f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        canvas.translate(mTmpBounds.left, mTmpBounds.top);
1974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1981f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // Handle RTL mirroring.
1991f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        final boolean needMirroring = needMirroring();
2004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (needMirroring) {
2011f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.translate(mTmpBounds.width(), 0);
2024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            canvas.scale(-1.0f, 1.0f);
2034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2051f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // At this point, canvas has been translated to the right position.
2061f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // And we use this bound for the destination rect for the drawBitmap, so
2071f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        // we offset to (0, 0);
2081f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mTmpBounds.offsetTo(0, 0);
2094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2101f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.createCachedBitmapIfNeeded(scaledWidth, scaledHeight);
2114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (!mAllowCaching) {
2121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
2134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else {
2144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mVectorState.canReuseCache()) {
2151f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mVectorState.updateCachedBitmap(scaledWidth, scaledHeight);
2164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.updateCacheStates();
2174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
2184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2191f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        mVectorState.drawCachedBitmapWithRootAlpha(canvas, colorFilter, mTmpBounds);
2204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        canvas.restoreToCount(saveCount);
2214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
22315375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
2244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getAlpha() {
2259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
226ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            return DrawableCompat.getAlpha(mDelegateDrawable);
2279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return mVectorState.mVPathRenderer.getRootAlpha();
2304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setAlpha(int alpha) {
2349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setAlpha(alpha);
2369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
2404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVectorState.mVPathRenderer.setRootAlpha(alpha);
2414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
2424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
2464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setColorFilter(ColorFilter colorFilter) {
2479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
2489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.setColorFilter(colorFilter);
2499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mColorFilter = colorFilter;
2534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        invalidateSelf();
2544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
2564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
2574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Ensures the tint filter is consistent with the current tint color and
2584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * mode.
2594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
2604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    PorterDuffColorFilter updateTintFilter(PorterDuffColorFilter tintFilter, ColorStateList tint,
2612c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                           PorterDuff.Mode tintMode) {
2624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint == null || tintMode == null) {
2634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return null;
2644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setMode, setColor of PorterDuffColorFilter are not public method in SDK v7.
2664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Therefore we create a new one all the time here. Don't expect this is called often.
2674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final int color = tint.getColorForState(getState(), Color.TRANSPARENT);
2684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return new PorterDuffColorFilter(color, tintMode);
2694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
27115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
2724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTint(int tint) {
2739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
274ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTint(mDelegateDrawable, tint);
2759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2779f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        setTintList(ColorStateList.valueOf(tint));
2794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
28115375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
2824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintList(ColorStateList tint) {
2839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
284ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintList(mDelegateDrawable, tint);
2859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
2869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
2879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
2889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
2894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != tint) {
2904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
2914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, tint, state.mTintMode);
2924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
2934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
2944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
2954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
29615375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
2974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void setTintMode(Mode tintMode) {
2989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
299ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.setTintMode(mDelegateDrawable, tintMode);
3009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
3019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
3044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTintMode != tintMode) {
3054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTintMode = tintMode;
3064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTintFilter = updateTintFilter(mTintFilter, state.mTint, tintMode);
3074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
3084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean isStateful() {
3139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.isStateful();
3159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return super.isStateful() || (mVectorState != null && mVectorState.mTint != null
3184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                && mVectorState.mTint.isStateful());
3194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    protected boolean onStateChange(int[] stateSet) {
3239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setState(stateSet);
3259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
3284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (state.mTint != null && state.mTintMode != null) {
3299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
3304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            invalidateSelf();
3314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
3324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
3344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getOpacity() {
3389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getOpacity();
3409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return PixelFormat.TRANSLUCENT;
3434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicWidth() {
3479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicWidth();
3499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseWidth;
3524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
3554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public int getIntrinsicHeight() {
3569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
3579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getIntrinsicHeight();
3589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return (int) mVectorState.mVPathRenderer.mBaseHeight;
3614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // Don't support re-applying themes. The initial theme loading is working.
36415375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
3654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public boolean canApplyTheme() {
3669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
367ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.canApplyTheme(mDelegateDrawable);
3689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
3699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
3704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
3714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
3744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * The size of a pixel when scaled from the intrinsic dimension to the viewport dimension. This
3754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * is used to calculate the path animation accuracy.
3764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
3774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @hide
3784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
379c39d9c75590eca86a5e7e32a8824ba04a0d42e9bAlan Viverette    @RestrictTo(GROUP_ID)
3804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public float getPixelSize() {
3814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (mVectorState == null && mVectorState.mVPathRenderer == null ||
3824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mBaseWidth == 0 ||
3834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mBaseHeight == 0 ||
3844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mViewportHeight == 0 ||
3854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVectorState.mVPathRenderer.mViewportWidth == 0) {
3864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return 1; // fall back to 1:1 pixel mapping.
3874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
3884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicWidth = mVectorState.mVPathRenderer.mBaseWidth;
3894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float intrinsicHeight = mVectorState.mVPathRenderer.mBaseHeight;
3904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportWidth = mVectorState.mVPathRenderer.mViewportWidth;
3914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float viewportHeight = mVectorState.mVPathRenderer.mViewportHeight;
3924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleX = viewportWidth / intrinsicWidth;
3934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float scaleY = viewportHeight / intrinsicHeight;
3944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return Math.min(scaleX, scaleY);
3954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
3964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
3974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
3984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Create a VectorDrawableCompat object.
3994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     *
4002c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu     * @param res   the resources.
4014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param resId the resource ID for VectorDrawableCompat object.
4024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @param theme the theme of this vector drawable, it can be null.
4034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * @return a new VectorDrawableCompat or null if parsing error is found.
4044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
4054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Nullable
4064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public static VectorDrawableCompat create(@NonNull Resources res, @DrawableRes int resId,
4072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                              @Nullable Theme theme) {
408c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu        if (Build.VERSION.SDK_INT >= 24) {
4099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final VectorDrawableCompat drawable = new VectorDrawableCompat();
410ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            drawable.mDelegateDrawable = ResourcesCompat.getDrawable(res, resId, theme);
4112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            drawable.mCachedConstantStateDelegate = new VectorDrawableDelegateState(
4122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    drawable.mDelegateDrawable.getConstantState());
4139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawable;
4149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        try {
4174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final XmlPullParser parser = res.getXml(resId);
4184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final AttributeSet attrs = Xml.asAttributeSet(parser);
4194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            int type;
4204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            while ((type = parser.next()) != XmlPullParser.START_TAG &&
4214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    type != XmlPullParser.END_DOCUMENT) {
4224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // Empty loop
4234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
4244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (type != XmlPullParser.START_TAG) {
4254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                throw new XmlPullParserException("No start tag found");
4264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
427e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            return createFromXmlInner(res, parser, attrs, theme);
4284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (XmlPullParserException e) {
4294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
4304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } catch (IOException e) {
4314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Log.e(LOGTAG, "parser error", e);
4324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
4334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return null;
4344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
436e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    /**
437e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * Create a VectorDrawableCompat from inside an XML document using an optional
438e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * {@link Theme}. Called on a parser positioned at a tag in an XML
439e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * document, tries to create a Drawable from that tag. Returns {@code null}
440e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     * if the tag is not a valid drawable.
441e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes     */
442e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    public static VectorDrawableCompat createFromXmlInner(Resources r, XmlPullParser parser,
443e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes            AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
444e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        final VectorDrawableCompat drawable = new VectorDrawableCompat();
445e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        drawable.inflate(r, parser, attrs, theme);
446e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes        return drawable;
447e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes    }
448e4beadba70aecabbd7f6677943ab7c0b94809b8aChris Banes
4498fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas    static int applyAlpha(int color, float alpha) {
4504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int alphaBytes = Color.alpha(color);
4514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color &= 0x00FFFFFF;
4524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        color |= ((int) (alphaBytes * alpha)) << 24;
4534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return color;
4544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    @Override
4574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs)
4584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
4599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
4609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.inflate(res, parser, attrs);
4619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflate(res, parser, attrs, null);
4654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
46715375aa6fd54b036f97f99229aefab2822c8a1c9Aurimas Liutikas    @Override
4684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
4694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throws XmlPullParserException, IOException {
4709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
471ebbed34a78fa6519de6c2848e68b97f9d3b98e08Tenghui Zhu            DrawableCompat.inflate(mDelegateDrawable, res, parser, attrs, theme);
4729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
4739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
4749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
4759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
4764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = new VPathRenderer();
4774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mVPathRenderer = pathRenderer;
4784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final TypedArray a = obtainAttributes(res, theme, attrs,
4809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawableTypeArray);
481d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
482d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        updateStateFromTypedArray(a, parser);
4834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        a.recycle();
4844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mChangingConfigurations = getChangingConfigurations();
4854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        state.mCacheDirty = true;
4864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        inflateInternal(res, parser, attrs, theme);
4874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
4884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
4894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
4904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
491d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
492d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    /**
493d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * Parses a {@link android.graphics.PorterDuff.Mode} from a tintMode
494d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     * attribute's enum value.
495d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu     */
4966705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu    private static PorterDuff.Mode parseTintModeCompat(int value, Mode defaultMode) {
497d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        switch (value) {
4982c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 3:
4992c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_OVER;
5002c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 5:
5012c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_IN;
5022c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 9:
5032c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SRC_ATOP;
5042c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 14:
5052c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.MULTIPLY;
5062c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 15:
5072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.SCREEN;
5082c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            case 16:
5092c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return Mode.ADD;
5102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            default:
5112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return defaultMode;
512d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
513d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu    }
514d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
5159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser)
5169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            throws XmlPullParserException {
5179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
5184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
5194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Account for any configuration changes.
5214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // state.mChangingConfigurations |= Utils.getChangingConfigurations(a);
5224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
523d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final int mode = TypedArrayUtils.getNamedInt(a, parser, "tintMode",
524d014251a4529b0eae3c313b7ede2b9d18421de44Chris Banes                AndroidResources.styleable_VectorDrawable_tintMode, -1);
5256705492013ac9cf97407565d7bdeb0af45598b5bTeng-Hui Zhu        state.mTintMode = parseTintModeCompat(mode, Mode.SRC_IN);
5264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5279f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final ColorStateList tint =
5289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                a.getColorStateList(AndroidResources.styleable_VectorDrawable_tint);
5294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (tint != null) {
5304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            state.mTint = tint;
5314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
533d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        state.mAutoMirrored = TypedArrayUtils.getNamedBoolean(a, parser, "autoMirrored",
5342c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_autoMirrored, state.mAutoMirrored);
535d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
536d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportWidth = TypedArrayUtils.getNamedFloat(a, parser, "viewportWidth",
5379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_viewportWidth,
5389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportWidth);
5394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
540d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        pathRenderer.mViewportHeight = TypedArrayUtils.getNamedFloat(a, parser, "viewportHeight",
5419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_viewportHeight,
5429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                pathRenderer.mViewportHeight);
5434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mViewportWidth <= 0) {
5454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportWidth > 0");
5474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mViewportHeight <= 0) {
5484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires viewportHeight > 0");
5504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseWidth = a.getDimension(
553d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_width, pathRenderer.mBaseWidth);
5544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.mBaseHeight = a.getDimension(
555d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                AndroidResources.styleable_VectorDrawable_height, pathRenderer.mBaseHeight);
5564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (pathRenderer.mBaseWidth <= 0) {
5574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires width > 0");
5594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        } else if (pathRenderer.mBaseHeight <= 0) {
5604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException(a.getPositionDescription() +
5614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    "<vector> tag requires height > 0");
5624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
564d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        // shown up from API 11.
565d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final float alphaInFloat = TypedArrayUtils.getNamedFloat(a, parser, "alpha",
566968dcfaff0c0a9e85ff4db2a985188f6996f5dadTeng-Hui Zhu                AndroidResources.styleable_VectorDrawable_alpha, pathRenderer.getAlpha());
5674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        pathRenderer.setAlpha(alphaInFloat);
5684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
569d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        final String name = a.getString(AndroidResources.styleable_VectorDrawable_name);
5704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (name != null) {
5714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mRootName = name;
5724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            pathRenderer.mVGTargetsMap.put(name, pathRenderer);
5734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
5744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
5754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
5772c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                 Theme theme) throws XmlPullParserException, IOException {
5789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        final VectorDrawableCompatState state = mVectorState;
5794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final VPathRenderer pathRenderer = state.mVPathRenderer;
5804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean noPathTag = true;
5814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Use a stack to help to build the group tree.
5834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // The top of the stack is always the current group.
5844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final Stack<VGroup> groupStack = new Stack<VGroup>();
5854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        groupStack.push(pathRenderer.mRootGroup);
5864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
5874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int eventType = parser.getEventType();
5884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        while (eventType != XmlPullParser.END_DOCUMENT) {
5894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (eventType == XmlPullParser.START_TAG) {
5904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
5914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final VGroup currentGroup = groupStack.peek();
5924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_PATH.equals(tagName)) {
5934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VFullPath path = new VFullPath();
594d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
5954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
5964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
5974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
5984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
5994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    noPathTag = false;
6004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
6014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_CLIP_PATH.equals(tagName)) {
6024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final VClipPath path = new VClipPath();
603d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    path.inflate(res, attrs, theme, parser);
6044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(path);
6054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (path.getPathName() != null) {
6064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(path.getPathName(), path);
6074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
6084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= path.mChangingConfigurations;
6094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (SHAPE_GROUP.equals(tagName)) {
6104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup newChildGroup = new VGroup();
611d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    newChildGroup.inflate(res, attrs, theme, parser);
6124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    currentGroup.mChildren.add(newChildGroup);
6134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.push(newChildGroup);
6144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newChildGroup.getGroupName() != null) {
6154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        pathRenderer.mVGTargetsMap.put(newChildGroup.getGroupName(),
6164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                                newChildGroup);
6174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
6184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    state.mChangingConfigurations |= newChildGroup.mChangingConfigurations;
6194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
6204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else if (eventType == XmlPullParser.END_TAG) {
6214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                final String tagName = parser.getName();
6224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (SHAPE_GROUP.equals(tagName)) {
6234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    groupStack.pop();
6244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
6254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
6264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            eventType = parser.next();
6274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the tree out for debug.
6304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (DBG_VECTOR_DRAWABLE) {
6314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            printGroupTree(pathRenderer.mRootGroup, 0);
6324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        if (noPathTag) {
6354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final StringBuffer tag = new StringBuffer();
6364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (tag.length() > 0) {
6384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                tag.append(" or ");
6394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
6404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            tag.append(SHAPE_PATH);
6414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            throw new XmlPullParserException("no " + tag + " defined");
6434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private void printGroupTree(VGroup currentGroup, int level) {
6474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String indent = "";
6484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < level; i++) {
6494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            indent += "    ";
6504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Print the current node
6524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "current group is :" + currentGroup.getGroupName()
6534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                + " rotation is " + currentGroup.mRotate);
6544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
6554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Then print all the children groups
6564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        for (int i = 0; i < currentGroup.mChildren.size(); i++) {
6574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Object child = currentGroup.mChildren.get(i);
6584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (child instanceof VGroup) {
6594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                printGroupTree((VGroup) child, level + 1);
660d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            } else {
661d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                ((VPath) child).printVPath(level + 1);
6624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
6634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
6644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    void setAllowCaching(boolean allowCaching) {
6674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        mAllowCaching = allowCaching;
6684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    // We don't support RTL auto mirroring since the getLayoutDirection() is for API 17+.
6714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private boolean needMirroring() {
6724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        return false;
6734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
6744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
6759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    // Extra override functions for delegation for SDK >= 7.
6769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
6775f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu    protected void onBoundsChange(Rect bounds) {
6789f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
6795f21d671a4afb439a61257b393d0b5e40879528aTeng-Hui Zhu            mDelegateDrawable.setBounds(bounds);
6809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6819f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
6829f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6839f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
6849f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public int getChangingConfigurations() {
6859f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
6869f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.getChangingConfigurations();
6879f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        return super.getChangingConfigurations() | mVectorState.getChangingConfigurations();
6899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
6909f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
6919f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
6929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void invalidateSelf() {
6939f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
6949f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.invalidateSelf();
6959f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
6969f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
6979f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.invalidateSelf();
6989f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
6999f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7009f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
7019f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void scheduleSelf(Runnable what, long when) {
7029f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
7039f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.scheduleSelf(what, when);
7049f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
7059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.scheduleSelf(what, when);
7079f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
7089f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7099f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
7109f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public boolean setVisible(boolean visible, boolean restart) {
7119f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
7129f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateDrawable.setVisible(visible, restart);
7139f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7149f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        return super.setVisible(visible, restart);
7159f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
7169f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7179f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    @Override
7189f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    public void unscheduleSelf(Runnable what) {
7199f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        if (mDelegateDrawable != null) {
7209f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateDrawable.unscheduleSelf(what);
7219f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return;
7229f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7239f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        super.unscheduleSelf(what);
7249f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
7259f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7269f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    /**
727c59ac731f7d38ee41d0aba567a9d3b77b40df628Teng-Hui Zhu     * Constant state for delegating the creating drawable job for SDK >= 24.
7289f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * Instead of creating a VectorDrawable, create a VectorDrawableCompat instance which contains
7299f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     * a delegated VectorDrawable instance.
7309f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu     */
7319f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableDelegateState extends ConstantState {
7329f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        private final ConstantState mDelegateState;
7332c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
7349f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableDelegateState(ConstantState state) {
7359f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            mDelegateState = state;
7369f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7379f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7389f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
7399f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable() {
7409f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
7419f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable();
7429f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
7439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7459f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
7469f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res) {
7479f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
7489f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable = (VectorDrawable) mDelegateState.newDrawable(res);
7499f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
7509f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7519f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7529f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
7539f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public Drawable newDrawable(Resources res, Theme theme) {
7549f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            VectorDrawableCompat drawableCompat = new VectorDrawableCompat();
7559f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            drawableCompat.mDelegateDrawable =
7569f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    (VectorDrawable) mDelegateState.newDrawable(res, theme);
7579f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return drawableCompat;
7589f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7599f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7609f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
7619f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public boolean canApplyTheme() {
7629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.canApplyTheme();
7639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7649f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7659f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        @Override
7669f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public int getChangingConfigurations() {
7679f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            return mDelegateState.getChangingConfigurations();
7689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        }
7699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    }
7709f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu
7719f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu    private static class VectorDrawableCompatState extends ConstantState {
7724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
7734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        VPathRenderer mVPathRenderer;
7744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mTint = null;
7754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mTintMode = DEFAULT_TINT_MODE;
7764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mAutoMirrored;
7774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Bitmap mCachedBitmap;
7794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int[] mCachedThemeAttrs;
7804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        ColorStateList mCachedTint;
7814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Mode mCachedTintMode;
7824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mCachedRootAlpha;
7834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCachedAutoMirrored;
7844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        boolean mCacheDirty;
7854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7862c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        /**
7872c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         * Temporary paint object used to draw cached bitmaps.
7882c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu         */
7894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint mTempPaint;
7904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
7914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Deep copy for mutate() or implicitly mutate.
7929f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState(VectorDrawableCompatState copy) {
7934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy != null) {
7944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mChangingConfigurations = copy.mChangingConfigurations;
7954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
7964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mFillPaint != null) {
7974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mFillPaint = new Paint(copy.mVPathRenderer.mFillPaint);
7984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
7994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copy.mVPathRenderer.mStrokePaint != null) {
8004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mVPathRenderer.mStrokePaint = new Paint(copy.mVPathRenderer.mStrokePaint);
8014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
8024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTint = copy.mTint;
8034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTintMode = copy.mTintMode;
8044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mAutoMirrored = copy.mAutoMirrored;
8054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8081f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void drawCachedBitmapWithRootAlpha(Canvas canvas, ColorFilter filter,
8091f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                                                  Rect originalBounds) {
8104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The bitmap's size is the same as the bounds.
8114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Paint p = getPaint(filter);
8121f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            canvas.drawBitmap(mCachedBitmap, null, originalBounds, p);
8134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean hasTranslucentRoot() {
8164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mVPathRenderer.getRootAlpha() < 255;
8174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /**
8204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * @return null when there is no need for alpha paint.
8214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
8224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Paint getPaint(ColorFilter filter) {
8234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!hasTranslucentRoot() && filter == null) {
8244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return null;
8254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mTempPaint == null) {
8284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint = new Paint();
8294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTempPaint.setFilterBitmap(true);
8304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setAlpha(mVPathRenderer.getRootAlpha());
8324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTempPaint.setColorFilter(filter);
8334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTempPaint;
8344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8361f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void updateCachedBitmap(int width, int height) {
8374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedBitmap.eraseColor(Color.TRANSPARENT);
8384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            Canvas tmpCanvas = new Canvas(mCachedBitmap);
8391f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            mVPathRenderer.draw(tmpCanvas, width, height, null);
8404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8421f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu        public void createCachedBitmapIfNeeded(int width, int height) {
8431f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu            if (mCachedBitmap == null || !canReuseBitmap(width, height)) {
8441f8664abb6cdd6962d58433e06dd9cc7ea856782Teng-Hui Zhu                mCachedBitmap = Bitmap.createBitmap(width, height,
8454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        Bitmap.Config.ARGB_8888);
8464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mCacheDirty = true;
8474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseBitmap(int width, int height) {
8524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (width == mCachedBitmap.getWidth()
8534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && height == mCachedBitmap.getHeight()) {
8544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
8554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
8574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canReuseCache() {
8604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!mCacheDirty
8614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTint == mTint
8624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedTintMode == mTintMode
8634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedAutoMirrored == mAutoMirrored
8644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    && mCachedRootAlpha == mVPathRenderer.getRootAlpha()) {
8654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return true;
8664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
8674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
8684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void updateCacheStates() {
8714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Use shallow copy here and shallow comparison in canReuseCache(),
8724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // likely hit cache miss more, but practically not much difference.
8734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTint = mTint;
8744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedTintMode = mTintMode;
8754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedRootAlpha = mVPathRenderer.getRootAlpha();
8764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCachedAutoMirrored = mAutoMirrored;
8774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mCacheDirty = false;
8784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu        public VectorDrawableCompatState() {
8814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mVPathRenderer = new VPathRenderer();
8824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
8854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable() {
8864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
8874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
8904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Drawable newDrawable(Resources res) {
8914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return new VectorDrawableCompat(this);
8924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
8944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
8954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getChangingConfigurations() {
8964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mChangingConfigurations;
8974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
8984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
8994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPathRenderer {
9014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Right now the internal data structure is organized as a tree.
9024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * Each node can be a group node, or a path.
9034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * A group node can have groups or paths as children, but a path node has
9044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * no children.
9054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         * One example can be:
9064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                 Root Group
9074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *                /    |     \
9084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *           Group    Path    Group
9094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *          /     \             |
9104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *         Path   Path         Path
9114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         *
9124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui         */
9134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables that only used temporarily inside the draw() call, so there
9144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // is no need for deep copying.
9154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mPath;
9164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Path mRenderPath;
9174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private static final Matrix IDENTITY_MATRIX = new Matrix();
9184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mFinalPathMatrix = new Matrix();
9194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mStrokePaint;
9214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint mFillPaint;
9224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private PathMeasure mPathMeasure;
9234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
9254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
9264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int mChangingConfigurations;
9278fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        final VGroup mRootGroup;
9284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseWidth = 0;
9294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mBaseHeight = 0;
9304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportWidth = 0;
9314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mViewportHeight = 0;
9324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mRootAlpha = 0xFF;
9334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mRootName = null;
9344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayMap<String, Object> mVGTargetsMap = new ArrayMap<String, Object>();
9364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer() {
9384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup();
9394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path();
9404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path();
9414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRootAlpha(int alpha) {
9444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = alpha;
9454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public int getRootAlpha() {
9484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRootAlpha;
9494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // setAlpha() and getAlpha() are used mostly for animation purpose, since
9524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Animator like to use alpha from 0 to 1.
9534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setAlpha(float alpha) {
9544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            setRootAlpha((int) (alpha * 255));
9554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
9584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getAlpha() {
9594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return getRootAlpha() / 255.0f;
9604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPathRenderer(VPathRenderer copy) {
9634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootGroup = new VGroup(copy.mRootGroup, mVGTargetsMap);
9644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPath = new Path(copy.mPath);
9654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath = new Path(copy.mRenderPath);
9664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseWidth = copy.mBaseWidth;
9674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mBaseHeight = copy.mBaseHeight;
9684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportWidth = copy.mViewportWidth;
9694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mViewportHeight = copy.mViewportHeight;
9704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
9714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootAlpha = copy.mRootAlpha;
9724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRootName = copy.mRootName;
9734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (copy.mRootName != null) {
9744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mVGTargetsMap.put(copy.mRootName, this);
9754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
9764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
9774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
9792c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                                   Canvas canvas, int w, int h, ColorFilter filter) {
9804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Calculate current group's matrix by preConcat the parent's and
9814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // and the current one on the top of the stack.
9824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Basically the Mfinal = Mviewport * M0 * M1 * M2;
9834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Mi the local matrix at level i of the group tree.
9844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.set(currentMatrix);
9854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
9864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
9874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
98804027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            // Save the current clip information, which is local to this group.
98904027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.save();
99004027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
9914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Draw the group tree in the same order as the XML file.
9924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < currentGroup.mChildren.size(); i++) {
9934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object child = currentGroup.mChildren.get(i);
9944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (child instanceof VGroup) {
9954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup childGroup = (VGroup) child;
9964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawGroupTree(childGroup, currentGroup.mStackedMatrix,
9974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                            canvas, w, h, filter);
9984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else if (child instanceof VPath) {
9994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath childPath = (VPath) child;
10004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    drawPath(currentGroup, childPath, canvas, w, h, filter);
10014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
10024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
100304027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu
100404027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu            canvas.restore();
10054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void draw(Canvas canvas, int w, int h, ColorFilter filter) {
1008c9a859537b0871f84afeeb706a5b425fe3f2b4ddAurimas Liutikas            // Traverse the tree in pre-order to draw.
10094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            drawGroupTree(mRootGroup, IDENTITY_MATRIX, canvas, w, h, filter);
10104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void drawPath(VGroup vGroup, VPath vPath, Canvas canvas, int w, int h,
10132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                              ColorFilter filter) {
10144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleX = w / mViewportWidth;
10154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float scaleY = h / mViewportHeight;
10164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final float minScale = Math.min(scaleX, scaleY);
10172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final Matrix groupStackedMatrix = vGroup.mStackedMatrix;
10184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10192c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFinalPathMatrix.set(groupStackedMatrix);
10204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFinalPathMatrix.postScale(scaleX, scaleY);
10214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10222c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
10232c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            final float matrixScale = getMatrixScale(groupStackedMatrix);
10242c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (matrixScale == 0) {
10252c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                // When either x or y is scaled to 0, we don't need to draw anything.
10262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                return;
10272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
10284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            vPath.toPath(mPath);
10294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final Path path = mPath;
10304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRenderPath.reset();
10324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (vPath.isClipPath()) {
10344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
103504027486ce99dc54f3ba88e517d76695c3ae90e8Teng-Hui Zhu                canvas.clipPath(mRenderPath);
10364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
10374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                VFullPath fullPath = (VFullPath) vPath;
10384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
10394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
10404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
10414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mPathMeasure == null) {
10434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure = new PathMeasure();
10444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mPathMeasure.setPath(mPath, false);
10464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    float len = mPathMeasure.getLength();
10484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    start = start * len;
10494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    end = end * len;
10504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.reset();
10514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (start > end) {
10524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, len, path, true);
10534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(0f, end, path, true);
10544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
10554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mPathMeasure.getSegment(start, end, path, true);
10564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    path.rLineTo(0, 0); // fix bug in measure
10584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
10594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRenderPath.addPath(path, mFinalPathMatrix);
10604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mFillColor != Color.TRANSPARENT) {
10624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mFillPaint == null) {
10634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint = new Paint();
10644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setStyle(Paint.Style.FILL);
10654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mFillPaint.setAntiAlias(true);
10664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint fillPaint = mFillPaint;
10694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
10704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    fillPaint.setColorFilter(filter);
10714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, fillPaint);
10724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
10734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (fullPath.mStrokeColor != Color.TRANSPARENT) {
10754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (mStrokePaint == null) {
10764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint = new Paint();
10774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setStyle(Paint.Style.STROKE);
10784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        mStrokePaint.setAntiAlias(true);
10794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    final Paint strokePaint = mStrokePaint;
10824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineJoin != null) {
10834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
10844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (fullPath.mStrokeLineCap != null) {
10874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
10884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
10894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
10904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
10914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
10924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    strokePaint.setColorFilter(filter);
10932c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    final float finalStrokeScale = minScale * matrixScale;
10942c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
10954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    canvas.drawPath(mRenderPath, strokePaint);
10964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
10974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
10984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
10992c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11002c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private static float cross(float v1x, float v1y, float v2x, float v2y) {
11012c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return v1x * v2y - v1y * v2x;
11022c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
11032c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11042c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        private float getMatrixScale(Matrix groupStackedMatrix) {
11052c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Given unit vectors A = (0, 1) and B = (1, 0).
11062c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
11072c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
11082c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
11092c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // If  max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
11102c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            //
11112c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For non-skew case, which is most of the cases, matrix scale is computing exactly the
11122c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // scale on x and y axis, and take the minimal of these two.
11132c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // For skew case, an unit square will mapped to a parallelogram. And this function will
11142c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            // return the minimal height of the 2 bases.
11152c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float[] unitVectors = new float[]{0, 1, 1, 0};
11162c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            groupStackedMatrix.mapVectors(unitVectors);
11172c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleX = (float) Math.hypot(unitVectors[0], unitVectors[1]);
11182c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float scaleY = (float) Math.hypot(unitVectors[2], unitVectors[3]);
11192c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float crossProduct = cross(unitVectors[0], unitVectors[1], unitVectors[2],
11202c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                    unitVectors[3]);
11212c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float maxScale = Math.max(scaleX, scaleY);
11222c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu
11232c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            float matrixScale = 0;
11242c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (maxScale > 0) {
11252c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                matrixScale = Math.abs(crossProduct) / maxScale;
11262c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
11272c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            if (DBG_VECTOR_DRAWABLE) {
11282c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu                Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
11292c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            }
11302c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            return matrixScale;
11312c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu        }
11324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
11334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VGroup {
11354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mStackedMatrix is only used temporarily when drawing, it combines all
11364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // the parents' local matrices with the current one.
11374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mStackedMatrix = new Matrix();
11384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
11404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
11414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        final ArrayList<Object> mChildren = new ArrayList<Object>();
11424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11438fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        float mRotate = 0;
11444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotX = 0;
11454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mPivotY = 0;
11464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleX = 1;
11474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mScaleY = 1;
11484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateX = 0;
11494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private float mTranslateY = 0;
11504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // mLocalMatrix is updated based on the update of transformation information,
11524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // either parsed from the XML or by animation.
11534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private final Matrix mLocalMatrix = new Matrix();
11548fbfb9b792b2978ba33bead0120a83b7af47a5f7Aurimas Liutikas        int mChangingConfigurations;
11554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
11564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private String mGroupName = null;
11574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup(VGroup copy, ArrayMap<String, Object> targetsMap) {
11594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mRotate = copy.mRotate;
11604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotX = copy.mPivotX;
11614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPivotY = copy.mPivotY;
11624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleX = copy.mScaleX;
11634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mScaleY = copy.mScaleY;
11644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateX = copy.mTranslateX;
11654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTranslateY = copy.mTranslateY;
11664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
11674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mGroupName = copy.mGroupName;
11684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
11694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mGroupName != null) {
11704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                targetsMap.put(mGroupName, this);
11714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
11724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.set(copy.mLocalMatrix);
11744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final ArrayList<Object> children = copy.mChildren;
11764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            for (int i = 0; i < children.size(); i++) {
11774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                Object copyChild = children.get(i);
11784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                if (copyChild instanceof VGroup) {
11794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VGroup copyGroup = (VGroup) copyChild;
11804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(new VGroup(copyGroup, targetsMap));
11814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                } else {
11824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    VPath newPath = null;
11834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (copyChild instanceof VFullPath) {
11844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VFullPath((VFullPath) copyChild);
11854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else if (copyChild instanceof VClipPath) {
11864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        newPath = new VClipPath((VClipPath) copyChild);
11874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    } else {
11884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        throw new IllegalStateException("Unknown object in the tree!");
11894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
11904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    mChildren.add(newPath);
11914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    if (newPath.mPathName != null) {
11924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                        targetsMap.put(newPath.mPathName, newPath);
11934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    }
11944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                }
11954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
11964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
11974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
11984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VGroup() {
11994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getGroupName() {
12024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mGroupName;
12034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public Matrix getLocalMatrix() {
12064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mLocalMatrix;
12074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1209d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources res, AttributeSet attrs, Theme theme, XmlPullParser parser) {
12104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(res, theme, attrs,
1211d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup);
1212d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
12134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
12144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1216d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
12174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
12184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
12194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
12214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
12224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1223d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1224d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mRotate = TypedArrayUtils.getNamedFloat(a, parser, "rotation",
1225d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_rotation, mRotate);
1226d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1227d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mPivotX = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotX, mPivotX);
1228d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mPivotY = a.getFloat(AndroidResources.styleable_VectorDrawableGroup_pivotY, mPivotY);
1229d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1230d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1231d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleX = TypedArrayUtils.getNamedFloat(a, parser, "scaleX",
1232d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_scaleX, mScaleX);
1233d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1234d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            // This is added in API 11
1235d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mScaleY = TypedArrayUtils.getNamedFloat(a, parser, "scaleY",
1236d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_scaleY, mScaleY);
1237d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1238d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateX = TypedArrayUtils.getNamedFloat(a, parser, "translateX",
1239d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_translateX, mTranslateX);
1240d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTranslateY = TypedArrayUtils.getNamedFloat(a, parser, "translateY",
1241d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableGroup_translateY, mTranslateY);
12424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12439f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String groupName =
12449f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableGroup_name);
12454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (groupName != null) {
12464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mGroupName = groupName;
12474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateLocalMatrix();
12504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateLocalMatrix() {
12534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // The order we apply is the same as the
12544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // RenderNode.cpp::applyViewPropertyTransforms().
12554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.reset();
12564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
12574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postScale(mScaleX, mScaleY);
12584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postRotate(mRotate, 0, 0);
12594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
12604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
12634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getRotation() {
12654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mRotate;
12664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setRotation(float rotation) {
12704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (rotation != mRotate) {
12714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mRotate = rotation;
12724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
12734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotX() {
12784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotX;
12794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotX(float pivotX) {
12834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotX != mPivotX) {
12844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotX = pivotX;
12854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
12864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
12874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getPivotY() {
12914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPivotY;
12924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
12934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
12944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
12954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPivotY(float pivotY) {
12964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pivotY != mPivotY) {
12974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPivotY = pivotY;
12984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
12994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleX() {
13044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleX;
13054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleX(float scaleX) {
13094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleX != mScaleX) {
13104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleX = scaleX;
13114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
13124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getScaleY() {
13174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mScaleY;
13184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setScaleY(float scaleY) {
13224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (scaleY != mScaleY) {
13234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mScaleY = scaleY;
13244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
13254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateX() {
13304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateX;
13314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateX(float translateX) {
13354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateX != mTranslateX) {
13364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateX = translateX;
13374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
13384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public float getTranslateY() {
13434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTranslateY;
13444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
13474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setTranslateY(float translateY) {
13484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (translateY != mTranslateY) {
13494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mTranslateY = translateY;
13504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                updateLocalMatrix();
13514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
13524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
13544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
13564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Common Path information for clip path and normal path.
13574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
13584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VPath {
13594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        protected PathParser.PathDataNode[] mNodes = null;
13604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        String mPathName;
13614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mChangingConfigurations;
13624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath() {
13644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
13654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1367d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void printVPath(int level) {
1368d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String indent = "";
1369d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < level; i++) {
1370d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                indent += "    ";
1371d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1372d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            Log.v(LOGTAG, indent + "current path is :" + mPathName +
1373d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    " pathData is " + NodesToString(mNodes));
1374d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1375d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1376d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1377d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public String NodesToString(PathParser.PathDataNode[] nodes) {
1378d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            String result = " ";
1379d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            for (int i = 0; i < nodes.length; i++) {
1380d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                result += nodes[i].type + ":";
1381d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                float[] params = nodes[i].params;
1382d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                for (int j = 0; j < params.length; j++) {
1383d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    result += params[j] + ",";
1384d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                }
1385d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1386d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            return result;
1387d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        }
1388d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
13894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VPath(VPath copy) {
13904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mPathName = copy.mPathName;
13914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mChangingConfigurations = copy.mChangingConfigurations;
13924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mNodes = PathParser.deepCopyNodes(copy.mNodes);
13934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
13944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
13954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void toPath(Path path) {
13964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            path.reset();
13974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mNodes != null) {
13984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.PathDataNode.nodesToPath(mNodes, path);
13994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public String getPathName() {
14034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mPathName;
14044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
14074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
14084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
14114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
14144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return false;
14154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
14184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public PathParser.PathDataNode[] getPathData() {
14204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mNodes;
14214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
14244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void setPathData(PathParser.PathDataNode[] nodes) {
14254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (!PathParser.canMorph(mNodes, nodes)) {
14264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                // This should not happen in the middle of animation.
14274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.deepCopyNodes(nodes);
14284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            } else {
14294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                PathParser.updateNodes(mNodes, nodes);
14304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
14334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
14354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Clip path, which only has name and pathData.
14364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
14374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VClipPath extends VPath {
14384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath() {
14394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
14404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VClipPath(VClipPath copy) {
14434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
14444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1446d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
14474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // TODO TINT THEME Not supported yet
1448d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1449d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
1450d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1451d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
14524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1453d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawableClipPath);
14544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            updateStateFromTypedArray(a);
14554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
14564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private void updateStateFromTypedArray(TypedArray a) {
14594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
14604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);;
14614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14629f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathName =
14639f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableClipPath_name);
14644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
14654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
14664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14689f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
14699f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawableClipPath_pathData);
14704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
14714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
14724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
14734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
14764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean isClipPath() {
14774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return true;
14784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
14794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
14804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    /**
14824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     * Normal path, which contains all the fill / paint information.
14834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui     */
14844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    private static class VFullPath extends VPath {
14854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /////////////////////////////////////////////////////
14864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        // Variables below need to be copied (deep copy if applicable) for mutation.
14874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private int[] mThemeAttrs;
14884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mStrokeColor = Color.TRANSPARENT;
14904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeWidth = 0;
14914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
14924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillColor = Color.TRANSPARENT;
14934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeAlpha = 1.0f;
14944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int mFillRule;
14954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mFillAlpha = 1.0f;
14964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathStart = 0;
14974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathEnd = 1;
14984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mTrimPathOffset = 0;
14994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
15014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
15024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float mStrokeMiterlimit = 4;
15034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath() {
15054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Empty constructor.
15064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public VFullPath(VFullPath copy) {
15094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            super(copy);
15104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = copy.mThemeAttrs;
15114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = copy.mStrokeColor;
15134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = copy.mStrokeWidth;
15144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = copy.mStrokeAlpha;
15154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = copy.mFillColor;
15164fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillRule = copy.mFillRule;
15174fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = copy.mFillAlpha;
15184fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = copy.mTrimPathStart;
15194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = copy.mTrimPathEnd;
15204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = copy.mTrimPathOffset;
15214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineCap = copy.mStrokeLineCap;
15234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeLineJoin = copy.mStrokeLineJoin;
15244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeMiterlimit = copy.mStrokeMiterlimit;
15254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Cap getStrokeLineCap(int id, Paint.Cap defValue) {
15284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
15294fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_BUTT:
15304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.BUTT;
15314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_ROUND:
15324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.ROUND;
15334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINECAP_SQUARE:
15344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Cap.SQUARE;
15354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
15364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
15374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        private Paint.Join getStrokeLineJoin(int id, Paint.Join defValue) {
15414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            switch (id) {
15424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_MITER:
15434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.MITER;
15444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_ROUND:
15454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.ROUND;
15464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                case LINEJOIN_BEVEL:
15474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return Paint.Join.BEVEL;
15484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                default:
15494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                    return defValue;
15504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
15544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public boolean canApplyTheme() {
15554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mThemeAttrs != null;
15564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1558d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        public void inflate(Resources r, AttributeSet attrs, Theme theme, XmlPullParser parser) {
15594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            final TypedArray a = obtainAttributes(r, theme, attrs,
1560d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath);
1561d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            updateStateFromTypedArray(a, parser);
15624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            a.recycle();
15634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
15644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1565d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu        private void updateStateFromTypedArray(TypedArray a, XmlPullParser parser) {
15664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Account for any configuration changes.
15674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // mChangingConfigurations |= Utils.getChangingConfigurations(a);
15684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            // Extract the theme attributes, if any.
15704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mThemeAttrs = null; // TODO TINT THEME Not supported yet a.extractThemeAttrs();
15714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
15729f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // In order to work around the conflicting id issue, we need to double check the
15739f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // existence of the attribute.
15749f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // B/c if the attribute existed in the compiled XML, then calling TypedArray will be
15759f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // safe since the framework will look up in the XML first.
15769f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            // Note that each getAttributeValue take roughly 0.03ms, it is a price we have to pay.
1577d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final boolean hasPathData = TypedArrayUtils.hasAttribute(parser, "pathData");
1578d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            if (!hasPathData) {
15799f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // If there is no pathData in the <path> tag, then this is an empty path,
15809f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                // nothing need to be drawn.
1581d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                return;
1582d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            }
1583d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu
1584d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final String pathName = a.getString(AndroidResources.styleable_VectorDrawablePath_name);
15854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathName != null) {
15864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mPathName = pathName;
15874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15889f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu            final String pathData =
15899f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    a.getString(AndroidResources.styleable_VectorDrawablePath_pathData);
15904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (pathData != null) {
15914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                mNodes = PathParser.createNodesFromPathData(pathData);
15924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
15934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
1594d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mFillColor = TypedArrayUtils.getNamedColor(a, parser, "fillColor",
1595d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_fillColor, mFillColor);
15962c3c8bff4c669316cdc2db24b72d9ac3f9b33725Teng-Hui Zhu            mFillAlpha = TypedArrayUtils.getNamedFloat(a, parser, "fillAlpha",
1597d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_fillAlpha, mFillAlpha);
1598d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineCap = TypedArrayUtils.getNamedInt(a, parser, "strokeLineCap",
1599d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeLineCap, -1);
1600d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineCap = getStrokeLineCap(lineCap, mStrokeLineCap);
1601d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            final int lineJoin = TypedArrayUtils.getNamedInt(a, parser, "strokeLineJoin",
1602d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeLineJoin, -1);
1603d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeLineJoin = getStrokeLineJoin(lineJoin, mStrokeLineJoin);
1604d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeMiterlimit = TypedArrayUtils.getNamedFloat(a, parser, "strokeMiterLimit",
16059f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeMiterLimit,
16069f8d3b8d31e1e6a4bbdc68563691650ebff21353Teng-Hui Zhu                    mStrokeMiterlimit);
1607d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeColor = TypedArrayUtils.getNamedColor(a, parser, "strokeColor",
1608d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeColor, mStrokeColor);
1609d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeAlpha = TypedArrayUtils.getNamedFloat(a, parser, "strokeAlpha",
1610d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeAlpha, mStrokeAlpha);
1611d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mStrokeWidth = TypedArrayUtils.getNamedFloat(a, parser, "strokeWidth",
1612d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_strokeWidth, mStrokeWidth);
1613d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathEnd = TypedArrayUtils.getNamedFloat(a, parser, "trimPathEnd",
1614d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathEnd, mTrimPathEnd);
1615d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathOffset = TypedArrayUtils.getNamedFloat(a, parser, "trimPathOffset",
1616d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathOffset, mTrimPathOffset);
1617d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu            mTrimPathStart = TypedArrayUtils.getNamedFloat(a, parser, "trimPathStart",
1618d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu                    AndroidResources.styleable_VectorDrawablePath_trimPathStart, mTrimPathStart);
16194fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16204fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16214fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @Override
16224fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        public void applyTheme(Theme t) {
16234fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            if (mThemeAttrs == null) {
16244fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui                return;
16254fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            }
16264fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16274fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            /*
16284fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * TODO TINT THEME Not supported yet final TypedArray a =
1629d85f3e0b931d3e127242a375e0d00c4696bba912Teng-Hui Zhu             * t.resolveAttributes(mThemeAttrs, styleable_VectorDrawablePath);
16304fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             * updateStateFromTypedArray(a); a.recycle();
16314fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui             */
16324fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16334fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16344fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
16354fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16364fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getStrokeColor() {
16374fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeColor;
16384fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16394fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16404fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16414fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeColor(int strokeColor) {
16424fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeColor = strokeColor;
16434fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16444fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16454fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16464fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeWidth() {
16474fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeWidth;
16484fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16494fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16504fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16514fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeWidth(float strokeWidth) {
16524fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeWidth = strokeWidth;
16534fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16544fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16554fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16564fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getStrokeAlpha() {
16574fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mStrokeAlpha;
16584fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16594fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16604fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16614fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setStrokeAlpha(float strokeAlpha) {
16624fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mStrokeAlpha = strokeAlpha;
16634fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16644fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16654fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16664fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        int getFillColor() {
16674fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillColor;
16684fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16694fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16704fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16714fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillColor(int fillColor) {
16724fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillColor = fillColor;
16734fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16744fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16754fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16764fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getFillAlpha() {
16774fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mFillAlpha;
16784fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16794fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16804fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16814fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setFillAlpha(float fillAlpha) {
16824fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mFillAlpha = fillAlpha;
16834fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16844fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16854fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16864fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathStart() {
16874fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathStart;
16884fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16894fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16904fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16914fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathStart(float trimPathStart) {
16924fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathStart = trimPathStart;
16934fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16944fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
16954fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
16964fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathEnd() {
16974fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathEnd;
16984fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
16994fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17004fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17014fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathEnd(float trimPathEnd) {
17024fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathEnd = trimPathEnd;
17034fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17044fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17054fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17064fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        float getTrimPathOffset() {
17074fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            return mTrimPathOffset;
17084fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17094fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui
17104fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        @SuppressWarnings("unused")
17114fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        void setTrimPathOffset(float trimPathOffset) {
17124fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui            mTrimPathOffset = trimPathOffset;
17134fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui        }
17144fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui    }
17154fcaa70c2362e58a3fb30d140f0a0eeda8e35b44ztenghui}
1716