VectorDrawable.h revision 1d8e194661085f9a18ab1b3cd12f9e19d3a86be5
14bbc2931263b232fba61807fca00e127573eff42Doris Liu/*
24bbc2931263b232fba61807fca00e127573eff42Doris Liu * Copyright (C) 2015 The Android Open Source Project
34bbc2931263b232fba61807fca00e127573eff42Doris Liu *
44bbc2931263b232fba61807fca00e127573eff42Doris Liu * Licensed under the Apache License, Version 2.0 (the "License");
54bbc2931263b232fba61807fca00e127573eff42Doris Liu * you may not use this file except in compliance with the License.
64bbc2931263b232fba61807fca00e127573eff42Doris Liu * You may obtain a copy of the License at
74bbc2931263b232fba61807fca00e127573eff42Doris Liu *
84bbc2931263b232fba61807fca00e127573eff42Doris Liu *      http://www.apache.org/licenses/LICENSE-2.0
94bbc2931263b232fba61807fca00e127573eff42Doris Liu *
104bbc2931263b232fba61807fca00e127573eff42Doris Liu * Unless required by applicable law or agreed to in writing, software
114bbc2931263b232fba61807fca00e127573eff42Doris Liu * distributed under the License is distributed on an "AS IS" BASIS,
124bbc2931263b232fba61807fca00e127573eff42Doris Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134bbc2931263b232fba61807fca00e127573eff42Doris Liu * See the License for the specific language governing permissions and
144bbc2931263b232fba61807fca00e127573eff42Doris Liu * limitations under the License.
154bbc2931263b232fba61807fca00e127573eff42Doris Liu */
164bbc2931263b232fba61807fca00e127573eff42Doris Liu
174bbc2931263b232fba61807fca00e127573eff42Doris Liu#ifndef ANDROID_HWUI_VPATH_H
184bbc2931263b232fba61807fca00e127573eff42Doris Liu#define ANDROID_HWUI_VPATH_H
194bbc2931263b232fba61807fca00e127573eff42Doris Liu
20dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include "hwui/Canvas.h"
211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#include "DisplayList.h"
22766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
234bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkBitmap.h>
244bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkColor.h>
251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#include <SkColorFilter.h>
26c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3bDoris Liu#include <SkCanvas.h>
274bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkMatrix.h>
284bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPaint.h>
294bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPath.h>
304bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPathMeasure.h>
314bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkRect.h>
32dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu#include <SkShader.h>
334bbc2931263b232fba61807fca00e127573eff42Doris Liu
344bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <cutils/compiler.h>
354bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <stddef.h>
364bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <vector>
374bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <string>
384bbc2931263b232fba61807fca00e127573eff42Doris Liu
394bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace android {
404bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace uirenderer {
414bbc2931263b232fba61807fca00e127573eff42Doris Liu
424bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace VectorDrawable {
431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP_AND_NOTIFY(field, value) ? (flag = true, true) : false)
444bbc2931263b232fba61807fca00e127573eff42Doris Liu#define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#define VD_SET_PROP_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP(field, value);\
461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    onPropertyChanged(); retVal;})
471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#define UPDATE_SKPROP(field, value) ({bool retVal = (field != value); if (field != value) SkRefCnt_SafeAssign(field, value); retVal;})
484bbc2931263b232fba61807fca00e127573eff42Doris Liu
494bbc2931263b232fba61807fca00e127573eff42Doris Liu/* A VectorDrawable is composed of a tree of nodes.
504bbc2931263b232fba61807fca00e127573eff42Doris Liu * Each node can be a group node, or a path.
514bbc2931263b232fba61807fca00e127573eff42Doris Liu * A group node can have groups or paths as children, but a path node has
524bbc2931263b232fba61807fca00e127573eff42Doris Liu * no children.
534bbc2931263b232fba61807fca00e127573eff42Doris Liu * One example can be:
544bbc2931263b232fba61807fca00e127573eff42Doris Liu *                 Root Group
554bbc2931263b232fba61807fca00e127573eff42Doris Liu *                /    |     \
564bbc2931263b232fba61807fca00e127573eff42Doris Liu *           Group    Path    Group
574bbc2931263b232fba61807fca00e127573eff42Doris Liu *          /     \             |
584bbc2931263b232fba61807fca00e127573eff42Doris Liu *         Path   Path         Path
594bbc2931263b232fba61807fca00e127573eff42Doris Liu *
601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * VectorDrawables are drawn into bitmap caches first, then the caches are drawn to the given
611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * canvas with root alpha applied. Two caches are maintained for VD, one in UI thread, the other in
621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Render Thread. A generation id is used to keep track of changes in the vector drawable tree.
631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Each cache has their own generation id to track whether they are up to date with the latest
641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * change in the tree.
651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Any property change to the vector drawable coming from UI thread (such as bulk setters to update
671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * all the properties, and viewport change, etc.) are only modifying the staging properties. The
681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties will then be marked dirty and will be pushed over to render thread properties
691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * at sync point. If staging properties are not dirty at sync point, we sync backwards by updating
701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties with render thread properties to reflect the latest animation value.
711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
724bbc2931263b232fba61807fca00e127573eff42Doris Liu */
731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuclass PropertyChangedListener {
751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liupublic:
761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener(bool* dirty, bool* stagingDirty)
771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            : mDirty(dirty), mStagingDirty(stagingDirty) {}
781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onPropertyChanged() {
791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            *mDirty = true;
801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onStagingPropertyChanged() {
821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            *mStagingDirty = true;
831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mDirty;
861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mStagingDirty;
871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu};
881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
894bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Node {
904bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class Properties {
921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Properties(Node* node) : mNode(node) {}
941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        inline void onPropertyChanged() {
951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mNode->onPropertyChanged(this);
961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Node* mNode;
991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1004bbc2931263b232fba61807fca00e127573eff42Doris Liu    Node(const Node& node) {
1014bbc2931263b232fba61807fca00e127573eff42Doris Liu        mName = node.mName;
1024bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
1034bbc2931263b232fba61807fca00e127573eff42Doris Liu    Node() {}
104c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3bDoris Liu    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
1051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleX, float scaleY, bool useStagingData) = 0;
1064bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual void dump() = 0;
1074bbc2931263b232fba61807fca00e127573eff42Doris Liu    void setName(const char* name) {
1084bbc2931263b232fba61807fca00e127573eff42Doris Liu        mName = name;
1094bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
1101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
1111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mPropertyChangedListener = listener;
1121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) = 0;
1144bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual ~Node(){}
1151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() = 0;
1164bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
1174bbc2931263b232fba61807fca00e127573eff42Doris Liu    std::string mName;
1181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener* mPropertyChangedListener = nullptr;
1194bbc2931263b232fba61807fca00e127573eff42Doris Liu};
1204bbc2931263b232fba61807fca00e127573eff42Doris Liu
1214bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Path : public Node {
1224bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
1234bbc2931263b232fba61807fca00e127573eff42Doris Liu    struct ANDROID_API Data {
1244bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<char> verbs;
1254bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<size_t> verbSizes;
1264bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<float> points;
1274bbc2931263b232fba61807fca00e127573eff42Doris Liu        bool operator==(const Data& data) const {
1284bbc2931263b232fba61807fca00e127573eff42Doris Liu            return verbs == data.verbs && verbSizes == data.verbSizes
1294bbc2931263b232fba61807fca00e127573eff42Doris Liu                    && points == data.points;
1304bbc2931263b232fba61807fca00e127573eff42Doris Liu        }
1314bbc2931263b232fba61807fca00e127573eff42Doris Liu    };
1321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class PathProperties : public Properties {
1341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
1351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        PathProperties(Node* node) : Properties(node) {}
1361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const PathProperties& prop) {
1371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = prop.mData;
1381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setData(const Data& data) {
1411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Updates the path data. Note that we don't generate a new Skia path right away
1421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // because there are cases where the animation is changing the path data, but the view
1431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // that hosts the VD has gone off screen, in which case we won't even draw. So we
1441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // postpone the Skia path generation to the draw time.
1451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (data == mData) {
1461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return;
1471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = data;
1491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        const Data& getData() const {
1531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mData;
1541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
1561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Data mData;
1571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1594bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const Path& path);
1604bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const char* path, size_t strLength);
1614bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path() {}
1621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1634bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
164c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3bDoris Liu    void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
1651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleX, float scaleY, bool useStagingData) override;
1664bbc2931263b232fba61807fca00e127573eff42Doris Liu    static float getMatrixScale(const SkMatrix& groupStackedMatrix);
1671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
1681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* prop) override {
1691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (prop == &mStagingProperties) {
1701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
1711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
1731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else if (prop == &mProperties){
1751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mSkPathDirty = true;
1761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
1781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateStagingProperties() { return &mStagingProperties; }
1821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const PathProperties* stagingProperties() { return &mStagingProperties; }
1831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
1851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateProperties() { return &mProperties; }
1864bbc2931263b232fba61807fca00e127573eff42Doris Liu
1874bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
1884bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual const SkPath& getUpdatedPath();
1891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void getStagingPath(SkPath* outPath);
19046591f4a2dbd785bcae2b82bb490e78208605ec8Teng-Hui Zhu    virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
1911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeScale, const SkMatrix& matrix, bool useStagingData) = 0;
1921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Internal data, render thread only.
1944bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mSkPathDirty = true;
1951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPath mSkPath;
1961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
1981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mProperties = PathProperties(this);
1991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mStagingProperties = PathProperties(this);
2001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
2014bbc2931263b232fba61807fca00e127573eff42Doris Liu};
2024bbc2931263b232fba61807fca00e127573eff42Doris Liu
2034bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API FullPath: public Path {
2044bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
2051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class FullPathProperties : public Properties {
2061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
2071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct PrimitiveFields {
2081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeWidth = 0;
2091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor strokeColor = SK_ColorTRANSPARENT;
2101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeAlpha = 1;
2111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor fillColor = SK_ColorTRANSPARENT;
2121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float fillAlpha = 1;
2131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathStart = 0;
2141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathEnd = 1;
2151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathOffset = 0;
2161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
2171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
2181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeMiterLimit = 4;
2191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int fillType = 0; /* non-zero or kWinding_FillType in Skia */
2201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
2211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
2221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const FullPathProperties& prop) {
2231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields = prop.mPrimitiveFields;
2241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
2251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillGradient.reset(prop.fillGradient);
2261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeGradient.reset(prop.strokeGradient);
2271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
2281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillGradient(SkShader* gradient) {
2301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if(fillGradient != gradient){
2311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                fillGradient.reset(gradient);
2321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeGradient(SkShader* gradient) {
2361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if(strokeGradient != gradient){
2371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                strokeGradient.reset(gradient);
2381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkShader* getFillGradient() const {
2421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return fillGradient;
2431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkShader* getStrokeGradient() const {
2451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return strokeGradient;
2461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeWidth() const{
2481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeWidth;
2491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeWidth(float strokeWidth) {
2511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(strokeWidth, strokeWidth);
2521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColor getStrokeColor() const{
2541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeColor;
2551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeColor(SkColor strokeColor) {
2571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeColor, strokeColor);
2581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeAlpha() const{
2601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeAlpha;
2611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeAlpha(float strokeAlpha) {
2631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.strokeAlpha, strokeAlpha);
2641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColor getFillColor() const {
2661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillColor;
2671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillColor(SkColor fillColor) {
2691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillColor, fillColor);
2701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getFillAlpha() const{
2721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillAlpha;
2731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillAlpha(float fillAlpha) {
2751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.fillAlpha, fillAlpha);
2761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathStart() const{
2781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathStart;
2791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathStart(float trimPathStart) {
2811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathStart, trimPathStart, mTrimDirty);
2821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathEnd() const{
2841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathEnd;
2851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathEnd(float trimPathEnd) {
2871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathEnd, trimPathEnd, mTrimDirty);
2881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathOffset() const{
2901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathOffset;
2911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathOffset(float trimPathOffset) {
2931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_WITH_FLAG(mPrimitiveFields.trimPathOffset, trimPathOffset, mTrimDirty);
2941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
295766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
2961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeMiterLimit() const {
2971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeMiterLimit;
2981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeLineCap() const {
3001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeLineCap;
3011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeLineJoin() const {
3031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeLineJoin;
3041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getFillType() const {
3061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillType;
3071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool copyProperties(int8_t* outProperties, int length) const;
3091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
3101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
3111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
3121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                int fillType) {
3131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeWidth = strokeWidth;
3141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeColor = strokeColor;
3151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeAlpha = strokeAlpha;
3161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillColor = fillColor;
3171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillAlpha = fillAlpha;
3181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathStart = trimPathStart;
3191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathEnd = trimPathEnd;
3201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathOffset = trimPathOffset;
3211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeMiterLimit = strokeMiterLimit;
3221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineCap = strokeLineCap;
3231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineJoin = strokeLineJoin;
3241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillType = fillType;
3251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
3261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
3271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Set property values during animation
3291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorPropertyValue(int propertyId, int32_t value);
3301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPropertyValue(int propertyId, float value);
3311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mTrimDirty;
3321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
3331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        enum class Property {
3341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeWidth = 0,
3351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeColor,
3361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeAlpha,
3371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillColor,
3381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillAlpha,
3391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathStart,
3401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathEnd,
3411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathOffset,
3421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineCap,
3431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineJoin,
3441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeMiterLimit,
3451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillType,
3461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            count,
3471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
3481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        PrimitiveFields mPrimitiveFields;
3491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkAutoTUnref<SkShader> fillGradient;
3501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkAutoTUnref<SkShader> strokeGradient;
3511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
352766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
3531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Called from UI thread
3544bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath(const FullPath& path); // for cloning
3554bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
3564bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath() : Path() {}
3571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void dump() override;
3581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateStagingProperties() { return &mStagingProperties; }
3591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const FullPathProperties* stagingProperties() { return &mStagingProperties; }
3601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
3621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateProperties() { return &mProperties; }
3631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
3651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
3661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Path::onPropertyChanged(properties);
3671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
3681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
3691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
3711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else if (properties == &mProperties) {
3731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
3751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3774bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
378dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
3794bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
3804bbc2931263b232fba61807fca00e127573eff42Doris Liu    const SkPath& getUpdatedPath() override;
3811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void getStagingPath(SkPath* outPath) override;
38246591f4a2dbd785bcae2b82bb490e78208605ec8Teng-Hui Zhu    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
3831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
3844bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
3851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mProperties = FullPathProperties(this);
3871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mStagingProperties = FullPathProperties(this);
3881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
3891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Intermediate data for drawing, render thread only
3914bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPath mTrimmedSkPath;
3921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3934bbc2931263b232fba61807fca00e127573eff42Doris Liu};
3944bbc2931263b232fba61807fca00e127573eff42Doris Liu
3954bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API ClipPath: public Path {
3964bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
3974bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const ClipPath& path) : Path(path) {}
3984bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
3994bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath() : Path() {}
4004bbc2931263b232fba61807fca00e127573eff42Doris Liu
4014bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
40246591f4a2dbd785bcae2b82bb490e78208605ec8Teng-Hui Zhu    void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
4031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeScale, const SkMatrix& matrix, bool useStagingData) override;
4044bbc2931263b232fba61807fca00e127573eff42Doris Liu};
4054bbc2931263b232fba61807fca00e127573eff42Doris Liu
4064bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Group: public Node {
4074bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
4081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class GroupProperties : public Properties {
4091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
4101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        GroupProperties(Node* mNode) : Properties(mNode) {}
4111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct PrimitiveFields {
4121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float rotate = 0;
4131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float pivotX = 0;
4141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float pivotY = 0;
4151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleX = 1;
4161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleY = 1;
4171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float translateX = 0;
4181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float translateY = 0;
4191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } mPrimitiveFields;
4201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const GroupProperties& prop) {
4211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields = prop.mPrimitiveFields;
4221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
4231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getRotation() const {
4251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.rotate;
4261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setRotation(float rotation) {
4281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.rotate, rotation);
4291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPivotX() const {
4311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.pivotX;
4321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPivotX(float pivotX) {
4341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotX, pivotX);
4351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPivotY() const {
4371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.pivotY;
4381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPivotY(float pivotY) {
4401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.pivotY, pivotY);
4411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaleX() const {
4431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.scaleX;
4441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaleX(float scaleX) {
4461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleX, scaleX);
4471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaleY() const {
4491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.scaleY;
4501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaleY(float scaleY) {
4521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.scaleY, scaleY);
4531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTranslateX() const {
4551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.translateX;
4561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateX(float translateX) {
4581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(mPrimitiveFields.translateX, translateX);
4591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTranslateY() const {
4611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.translateY;
4621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateY(float translateY) {
4641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            VD_SET_PROP_AND_NOTIFY(translateY, translateY);
4651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void updateProperties(float rotate, float pivotX, float pivotY,
4671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                float scaleX, float scaleY, float translateX, float translateY) {
4681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.rotate = rotate;
4691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.pivotX = pivotX;
4701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.pivotY = pivotY;
4711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.scaleX = scaleX;
4721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.scaleY = scaleY;
4731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.translateX = translateX;
4741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.translateY = translateY;
4751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
4761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPropertyValue(int propertyId, float value);
4781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPropertyValue(int propertyId) const;
4791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool copyProperties(float* outProperties, int length) const;
4801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        static bool isValidProperty(int propertyId);
4811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
4821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        enum class Property {
4831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            rotate = 0,
4841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            pivotX,
4851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            pivotY,
4861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            scaleX,
4871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            scaleY,
4881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            translateX,
4891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            translateY,
4901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Count of the properties, must be at the end.
4911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            count,
4921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
493766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    };
4941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
4954bbc2931263b232fba61807fca00e127573eff42Doris Liu    Group(const Group& group);
4964bbc2931263b232fba61807fca00e127573eff42Doris Liu    Group() {}
4971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void addChild(Node* child);
4981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void setPropertyChangedListener(PropertyChangedListener* listener) override {
4991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Node::setPropertyChangedListener(listener);
5001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        for (auto& child : mChildren) {
5011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu             child->setPropertyChangedListener(listener);
5021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5034bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
5041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
5051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties* mutateStagingProperties() { return &mStagingProperties; }
5061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const GroupProperties* stagingProperties() { return &mStagingProperties; }
5071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
5091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties* mutateProperties() { return &mProperties; }
5101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Methods below could be called from either UI thread or Render Thread.
512c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3bDoris Liu    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
5131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleX, float scaleY, bool useStagingData) override;
5141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties);
5154bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
516766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    static bool isValidProperty(int propertyId);
5174bbc2931263b232fba61807fca00e127573eff42Doris Liu
5181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
5191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
5201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
5211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
5221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
5231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
5251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
5261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
5271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5314bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
5321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mProperties = GroupProperties(this);
5331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mStagingProperties = GroupProperties(this);
5341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
535ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    std::vector< std::unique_ptr<Node> > mChildren;
5364bbc2931263b232fba61807fca00e127573eff42Doris Liu};
5374bbc2931263b232fba61807fca00e127573eff42Doris Liu
538766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuclass ANDROID_API Tree : public VirtualLightRefBase {
5394bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
5401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Tree(Group* rootNode) : mRootNode(rootNode) {
5411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
5421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5434bbc2931263b232fba61807fca00e127573eff42Doris Liu    void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
5444bbc2931263b232fba61807fca00e127573eff42Doris Liu            const SkRect& bounds, bool needsMirroring, bool canReuseCache);
5451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void drawStaging(Canvas* canvas);
5464bbc2931263b232fba61807fca00e127573eff42Doris Liu
547766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    const SkBitmap& getBitmapUpdateIfDirty();
5484bbc2931263b232fba61807fca00e127573eff42Doris Liu    void setAllowCaching(bool allowCaching) {
5494bbc2931263b232fba61807fca00e127573eff42Doris Liu        mAllowCaching = allowCaching;
5504bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
551766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    SkPaint* getPaint();
5521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void syncProperties() {
5531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mNonAnimatablePropertiesDirty) {
5541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncNonAnimatableProperties(mStagingProperties);
5551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.mNonAnimatablePropertiesDirty = false;
5561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mAnimatablePropertiesDirty) {
5591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncAnimatableProperties(mStagingProperties);
5601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
5611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.syncAnimatableProperties(mProperties);
5621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mStagingProperties.mAnimatablePropertiesDirty = false;
5641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->syncProperties();
5651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class TreeProperties {
5681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
5691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        TreeProperties(Tree* tree) : mTree(tree) {}
5701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Properties that can only be modified by UI thread, therefore sync should
5711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // only go from UI to RT
5721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct NonAnimatableProperties {
5731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportWidth = 0;
5741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportHeight = 0;
5751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkRect bounds;
5761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledWidth = 0;
5771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledHeight = 0;
5781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColorFilter* colorFilter = nullptr;
5791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            ~NonAnimatableProperties() {
5801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkSafeUnref(colorFilter);
5811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } mNonAnimatableProperties;
5831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mNonAnimatablePropertiesDirty = true;
5841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float mRootAlpha = 1.0f;
5861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mAnimatablePropertiesDirty = true;
5871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncNonAnimatableProperties(const TreeProperties& prop) {
5891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Copy over the data that can only be changed in UI thread
5901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
5911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
5921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                        prop.mNonAnimatableProperties.colorFilter);
5931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mNonAnimatableProperties = prop.mNonAnimatableProperties;
5951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setViewportSize(float width, float height) {
5981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.viewportWidth != width
5991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                    || mNonAnimatableProperties.viewportHeight != height) {
6001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportWidth = width;
6021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportHeight = height;
6031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setBounds(const SkRect& bounds) {
6071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.bounds != bounds) {
6081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.bounds = bounds;
6091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaledSize(int width, int height) {
6151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.scaledWidth != width
6161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                    || mNonAnimatableProperties.scaledHeight != height) {
6171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.scaledWidth = width;
6181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.scaledHeight = height;
6191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorFilter(SkColorFilter* filter) {
6241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
6251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColorFilter* getColorFilter() const{
6301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.colorFilter;
6311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getViewportWidth() const {
6341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.viewportWidth;
6351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getViewportHeight() const {
6371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.viewportHeight;
6381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaledWidth() const {
6401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.scaledWidth;
6411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaledHeight() const {
6431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.scaledHeight;
6441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncAnimatableProperties(const TreeProperties& prop) {
6461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mRootAlpha = prop.mRootAlpha;
6471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool setRootAlpha(float rootAlpha) {
6491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (rootAlpha != mRootAlpha) {
6501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mAnimatablePropertiesDirty = true;
6511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mRootAlpha = rootAlpha;
6521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return true;
6541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return false;
6561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getRootAlpha() const { return mRootAlpha;}
6581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        const SkRect& getBounds() const {
6591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.bounds;
6601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Tree* mTree;
6621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
6631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onPropertyChanged(TreeProperties* prop);
6641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
6651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const TreeProperties* stagingProperties() { return &mStagingProperties; }
6661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PushStagingFunctor* getFunctor() { return &mFunctor;}
6671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
6691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateProperties() { return &mProperties; }
6704bbc2931263b232fba61807fca00e127573eff42Doris Liu
6714bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
6721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class VectorDrawableFunctor : public PushStagingFunctor {
6731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
6741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        VectorDrawableFunctor(Tree* tree) : mTree(tree) {}
6751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        virtual void operator ()() {
6761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTree->syncProperties();
6771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
6791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Tree* mTree;
6801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
6811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
6831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool allocateBitmapIfNeeded(SkBitmap* outCache, int width, int height);
6841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool canReuseBitmap(const SkBitmap&, int width, int height);
6851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void updateBitmapCache(SkBitmap* outCache, bool useStagingData);
6864bbc2931263b232fba61807fca00e127573eff42Doris Liu    // Cap the bitmap size, such that it won't hurt the performance too much
6874bbc2931263b232fba61807fca00e127573eff42Doris Liu    // and it won't crash due to a very large scale.
6884bbc2931263b232fba61807fca00e127573eff42Doris Liu    // The drawable will look blurry above this size.
6894bbc2931263b232fba61807fca00e127573eff42Doris Liu    const static int MAX_CACHED_BITMAP_SIZE;
6904bbc2931263b232fba61807fca00e127573eff42Doris Liu
6914bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mAllowCaching = true;
692ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    std::unique_ptr<Group> mRootNode;
6931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mProperties = TreeProperties(this);
6951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mStagingProperties = TreeProperties(this);
6961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    VectorDrawableFunctor mFunctor = VectorDrawableFunctor(this);
6981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6994bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPaint mPaint;
7001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    struct Cache {
7011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkBitmap bitmap;
7021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool dirty = true;
7031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
7041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mStagingCache;
7061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mCache;
7074bbc2931263b232fba61807fca00e127573eff42Doris Liu
7081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener mPropertyChangedListener
7091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
7104bbc2931263b232fba61807fca00e127573eff42Doris Liu};
7114bbc2931263b232fba61807fca00e127573eff42Doris Liu
7124bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace VectorDrawable
7134bbc2931263b232fba61807fca00e127573eff42Doris Liu
7144bbc2931263b232fba61807fca00e127573eff42Doris Liutypedef VectorDrawable::Path::Data PathData;
7154bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace uirenderer
7164bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace android
7174bbc2931263b232fba61807fca00e127573eff42Doris Liu
7184bbc2931263b232fba61807fca00e127573eff42Doris Liu#endif // ANDROID_HWUI_VPATH_H
719