VectorDrawable.h revision 3310fb1b24c6cdd0781674fab69e359caf9d17e5
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"
21fc9999505a36c66892d7ccce85187936105f4f36sergeyv#include "hwui/Bitmap.h"
223310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev#include "renderthread/CacheManager.h"
231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#include "DisplayList.h"
24766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
254bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkBitmap.h>
264bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkColor.h>
271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#include <SkColorFilter.h>
28c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3bDoris Liu#include <SkCanvas.h>
294bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkMatrix.h>
304bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPaint.h>
314bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPath.h>
324bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkPathMeasure.h>
334bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkRect.h>
34dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu#include <SkShader.h>
3523c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev#include <SkSurface.h>
364bbc2931263b232fba61807fca00e127573eff42Doris Liu
374bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <cutils/compiler.h>
384bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <stddef.h>
394bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <vector>
404bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <string>
414bbc2931263b232fba61807fca00e127573eff42Doris Liu
424bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace android {
434bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace uirenderer {
444bbc2931263b232fba61807fca00e127573eff42Doris Liu
4585d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu// Debug
4685d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#if DEBUG_VECTOR_DRAWABLE
4785d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu    #define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__)
4885d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#else
4985d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu    #define VECTOR_DRAWABLE_LOGD(...)
5085d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#endif
5185d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu
524bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace VectorDrawable {
5332d7cda0b89a114171f14de0753674090b3d75fcDoris Liu#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
5432d7cda0b89a114171f14de0753674090b3d75fcDoris Liu#define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false)
5532d7cda0b89a114171f14de0753674090b3d75fcDoris Liu#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value) ({ bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value));\
561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    onPropertyChanged(); retVal;})
5732d7cda0b89a114171f14de0753674090b3d75fcDoris Liu#define UPDATE_SKPROP(field, value) ({bool retVal = ((field) != (value)); if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); retVal;})
584bbc2931263b232fba61807fca00e127573eff42Doris Liu
594bbc2931263b232fba61807fca00e127573eff42Doris Liu/* A VectorDrawable is composed of a tree of nodes.
604bbc2931263b232fba61807fca00e127573eff42Doris Liu * Each node can be a group node, or a path.
614bbc2931263b232fba61807fca00e127573eff42Doris Liu * A group node can have groups or paths as children, but a path node has
624bbc2931263b232fba61807fca00e127573eff42Doris Liu * no children.
634bbc2931263b232fba61807fca00e127573eff42Doris Liu * One example can be:
644bbc2931263b232fba61807fca00e127573eff42Doris Liu *                 Root Group
654bbc2931263b232fba61807fca00e127573eff42Doris Liu *                /    |     \
664bbc2931263b232fba61807fca00e127573eff42Doris Liu *           Group    Path    Group
674bbc2931263b232fba61807fca00e127573eff42Doris Liu *          /     \             |
684bbc2931263b232fba61807fca00e127573eff42Doris Liu *         Path   Path         Path
694bbc2931263b232fba61807fca00e127573eff42Doris Liu *
701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * VectorDrawables are drawn into bitmap caches first, then the caches are drawn to the given
711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * canvas with root alpha applied. Two caches are maintained for VD, one in UI thread, the other in
721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Render Thread. A generation id is used to keep track of changes in the vector drawable tree.
731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Each cache has their own generation id to track whether they are up to date with the latest
741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * change in the tree.
751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Any property change to the vector drawable coming from UI thread (such as bulk setters to update
771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * all the properties, and viewport change, etc.) are only modifying the staging properties. The
781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties will then be marked dirty and will be pushed over to render thread properties
791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * at sync point. If staging properties are not dirty at sync point, we sync backwards by updating
801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties with render thread properties to reflect the latest animation value.
811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
824bbc2931263b232fba61807fca00e127573eff42Doris Liu */
831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuclass PropertyChangedListener {
851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liupublic:
861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener(bool* dirty, bool* stagingDirty)
871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            : mDirty(dirty), mStagingDirty(stagingDirty) {}
881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onPropertyChanged() {
891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            *mDirty = true;
901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onStagingPropertyChanged() {
921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            *mStagingDirty = true;
931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mDirty;
961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mStagingDirty;
971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu};
981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
994bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Node {
1004bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
1011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class Properties {
1021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
103a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit Properties(Node* node) : mNode(node) {}
1041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        inline void onPropertyChanged() {
1051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mNode->onPropertyChanged(this);
1061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
1081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Node* mNode;
1091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1104bbc2931263b232fba61807fca00e127573eff42Doris Liu    Node(const Node& node) {
1114bbc2931263b232fba61807fca00e127573eff42Doris Liu        mName = node.mName;
1124bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
1134bbc2931263b232fba61807fca00e127573eff42Doris Liu    Node() {}
114cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual void draw(SkCanvas* outCanvas, bool useStagingData) = 0;
1154bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual void dump() = 0;
1164bbc2931263b232fba61807fca00e127573eff42Doris Liu    void setName(const char* name) {
1174bbc2931263b232fba61807fca00e127573eff42Doris Liu        mName = name;
1184bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
1191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
1201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mPropertyChangedListener = listener;
1211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) = 0;
1234bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual ~Node(){}
1241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() = 0;
1254bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
1264bbc2931263b232fba61807fca00e127573eff42Doris Liu    std::string mName;
1271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener* mPropertyChangedListener = nullptr;
1284bbc2931263b232fba61807fca00e127573eff42Doris Liu};
1294bbc2931263b232fba61807fca00e127573eff42Doris Liu
1304bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Path : public Node {
1314bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
1324bbc2931263b232fba61807fca00e127573eff42Doris Liu    struct ANDROID_API Data {
1334bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<char> verbs;
1344bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<size_t> verbSizes;
1354bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<float> points;
1364bbc2931263b232fba61807fca00e127573eff42Doris Liu        bool operator==(const Data& data) const {
1374bbc2931263b232fba61807fca00e127573eff42Doris Liu            return verbs == data.verbs && verbSizes == data.verbSizes
1384bbc2931263b232fba61807fca00e127573eff42Doris Liu                    && points == data.points;
1394bbc2931263b232fba61807fca00e127573eff42Doris Liu        }
1404bbc2931263b232fba61807fca00e127573eff42Doris Liu    };
1411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class PathProperties : public Properties {
1431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
144a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit PathProperties(Node* node) : Properties(node) {}
1451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const PathProperties& prop) {
1461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = prop.mData;
1471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setData(const Data& data) {
1501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Updates the path data. Note that we don't generate a new Skia path right away
1511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // because there are cases where the animation is changing the path data, but the view
1521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // that hosts the VD has gone off screen, in which case we won't even draw. So we
1531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // postpone the Skia path generation to the draw time.
1541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (data == mData) {
1551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return;
1561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = data;
1581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        const Data& getData() const {
1621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mData;
1631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
1651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Data mData;
1661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1684bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const Path& path);
1694bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const char* path, size_t strLength);
1704bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path() {}
1711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1724bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
1731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
1741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* prop) override {
1751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (prop == &mStagingProperties) {
1761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
1771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
1791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else if (prop == &mProperties){
1811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mSkPathDirty = true;
1821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
1841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateStagingProperties() { return &mStagingProperties; }
1881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const PathProperties* stagingProperties() { return &mStagingProperties; }
1891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
1911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateProperties() { return &mProperties; }
1924bbc2931263b232fba61807fca00e127573eff42Doris Liu
1934bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
194cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath);
1951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Internal data, render thread only.
1974bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mSkPathDirty = true;
1981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPath mSkPath;
1991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
2001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
2011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mProperties = PathProperties(this);
2021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mStagingProperties = PathProperties(this);
2031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
2044bbc2931263b232fba61807fca00e127573eff42Doris Liu};
2054bbc2931263b232fba61807fca00e127573eff42Doris Liu
2064bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API FullPath: public Path {
2074bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
2081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class FullPathProperties : public Properties {
2091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
2101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct PrimitiveFields {
2111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeWidth = 0;
2121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor strokeColor = SK_ColorTRANSPARENT;
2131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeAlpha = 1;
2141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor fillColor = SK_ColorTRANSPARENT;
2151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float fillAlpha = 1;
2161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathStart = 0;
2171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathEnd = 1;
2181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathOffset = 0;
2191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
2201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
2211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeMiterLimit = 4;
2221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int fillType = 0; /* non-zero or kWinding_FillType in Skia */
2231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
224a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
225ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        ~FullPathProperties() {
226ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            SkSafeUnref(fillGradient);
227ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            SkSafeUnref(strokeGradient);
228ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        }
2291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const FullPathProperties& prop) {
2301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields = prop.mPrimitiveFields;
2311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
232ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            UPDATE_SKPROP(fillGradient, prop.fillGradient);
233ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            UPDATE_SKPROP(strokeGradient, prop.strokeGradient);
2341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
2351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillGradient(SkShader* gradient) {
237ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            if(UPDATE_SKPROP(fillGradient, gradient)) {
2381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeGradient(SkShader* gradient) {
242ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            if(UPDATE_SKPROP(strokeGradient, gradient)) {
2431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkShader* getFillGradient() const {
2471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return fillGradient;
2481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkShader* getStrokeGradient() const {
2501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return strokeGradient;
2511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeWidth() const{
2531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeWidth;
2541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeWidth(float strokeWidth) {
25632d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
2571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColor getStrokeColor() const{
2591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeColor;
2601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeColor(SkColor strokeColor) {
26232d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeColor, strokeColor);
2631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeAlpha() const{
2651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeAlpha;
2661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeAlpha(float strokeAlpha) {
26832d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeAlpha, strokeAlpha);
2691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColor getFillColor() const {
2711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillColor;
2721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillColor(SkColor fillColor) {
27432d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillColor, fillColor);
2751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getFillAlpha() const{
2771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillAlpha;
2781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillAlpha(float fillAlpha) {
28032d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillAlpha, fillAlpha);
2811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathStart() const{
2831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathStart;
2841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathStart(float trimPathStart) {
28632d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathStart, trimPathStart, mTrimDirty);
2871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathEnd() const{
2891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathEnd;
2901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathEnd(float trimPathEnd) {
29232d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathEnd, trimPathEnd, mTrimDirty);
2931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTrimPathOffset() const{
2951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.trimPathOffset;
2961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathOffset(float trimPathOffset) {
29832d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathOffset, trimPathOffset, mTrimDirty);
2991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
300766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
3011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeMiterLimit() const {
3021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeMiterLimit;
3031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeLineCap() const {
3051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeLineCap;
3061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getStrokeLineJoin() const {
3081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.strokeLineJoin;
3091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getFillType() const {
3111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.fillType;
3121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool copyProperties(int8_t* outProperties, int length) const;
3141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
3151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkColor fillColor, float fillAlpha, float trimPathStart, float trimPathEnd,
3161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                float trimPathOffset, float strokeMiterLimit, int strokeLineCap, int strokeLineJoin,
3171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                int fillType) {
3181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeWidth = strokeWidth;
3191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeColor = strokeColor;
3201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeAlpha = strokeAlpha;
3211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillColor = fillColor;
3221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillAlpha = fillAlpha;
3231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathStart = trimPathStart;
3241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathEnd = trimPathEnd;
3251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathOffset = trimPathOffset;
3261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeMiterLimit = strokeMiterLimit;
3271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineCap = strokeLineCap;
3281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineJoin = strokeLineJoin;
3291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillType = fillType;
3301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
3311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
3321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Set property values during animation
3341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorPropertyValue(int propertyId, int32_t value);
3351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPropertyValue(int propertyId, float value);
3361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mTrimDirty;
3371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
3381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        enum class Property {
3391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeWidth = 0,
3401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeColor,
3411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeAlpha,
3421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillColor,
3431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillAlpha,
3441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathStart,
3451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathEnd,
3461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathOffset,
3471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineCap,
3481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineJoin,
3491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeMiterLimit,
3501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillType,
3511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            count,
3521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
3531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        PrimitiveFields mPrimitiveFields;
354ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        SkShader* fillGradient = nullptr;
355ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        SkShader* strokeGradient = nullptr;
3561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
357766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
3581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Called from UI thread
3594bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath(const FullPath& path); // for cloning
3604bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
3614bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath() : Path() {}
362cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    void draw(SkCanvas* outCanvas, bool useStagingData) override;
3631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void dump() override;
3641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateStagingProperties() { return &mStagingProperties; }
3651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const FullPathProperties* stagingProperties() { return &mStagingProperties; }
3661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
3681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateProperties() { return &mProperties; }
3691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
3711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
3721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Path::onPropertyChanged(properties);
3731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
3741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
3751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
3771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else if (properties == &mProperties) {
3791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
3811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3834bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
384dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
3854bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
386cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) override;
3874bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
3881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mProperties = FullPathProperties(this);
3901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mStagingProperties = FullPathProperties(this);
3911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
3921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Intermediate data for drawing, render thread only
3944bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPath mTrimmedSkPath;
3951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3964bbc2931263b232fba61807fca00e127573eff42Doris Liu};
3974bbc2931263b232fba61807fca00e127573eff42Doris Liu
3984bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API ClipPath: public Path {
3994bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
4004bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const ClipPath& path) : Path(path) {}
4014bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
4024bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath() : Path() {}
403cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    void draw(SkCanvas* outCanvas, 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:
410a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit 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) {
42832d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation);
4291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPivotX() const {
4311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.pivotX;
4321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPivotX(float pivotX) {
43432d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX);
4351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPivotY() const {
4371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.pivotY;
4381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPivotY(float pivotY) {
44032d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY);
4411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaleX() const {
4431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.scaleX;
4441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaleX(float scaleX) {
44632d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX);
4471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaleY() const {
4491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.scaleY;
4501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaleY(float scaleY) {
45232d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY);
4531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTranslateX() const {
4551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.translateX;
4561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateX(float translateX) {
45832d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateX, translateX);
4591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getTranslateY() const {
4611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mPrimitiveFields.translateY;
4621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateY(float translateY) {
46432d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_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.
512cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual void draw(SkCanvas* outCanvas, bool useStagingData) override;
5131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties);
5144bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
515766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    static bool isValidProperty(int propertyId);
5164bbc2931263b232fba61807fca00e127573eff42Doris Liu
5171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
5181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
5191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
5201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
5211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
5221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
5241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
5251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
5261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5304bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
5311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mProperties = GroupProperties(this);
5321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mStagingProperties = GroupProperties(this);
5331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
534ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    std::vector< std::unique_ptr<Node> > mChildren;
5354bbc2931263b232fba61807fca00e127573eff42Doris Liu};
5364bbc2931263b232fba61807fca00e127573eff42Doris Liu
537766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuclass ANDROID_API Tree : public VirtualLightRefBase {
5384bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
539a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh    explicit Tree(Group* rootNode) : mRootNode(rootNode) {
5401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
5411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
542335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu
543335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    // Copy properties from the tree and use the give node as the root node
544335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    Tree(const Tree* copy, Group* rootNode) : Tree(rootNode) {
545335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu        mStagingProperties.syncAnimatableProperties(*copy->stagingProperties());
546335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu        mStagingProperties.syncNonAnimatableProperties(*copy->stagingProperties());
547335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    }
548f8d131cc8dc4ef675b8f8fc57dcc26062d575d32Doris Liu    // Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input
549f8d131cc8dc4ef675b8f8fc57dcc26062d575d32Doris Liu    // canvas. Returns the number of pixels needed for the bitmap cache.
550f8d131cc8dc4ef675b8f8fc57dcc26062d575d32Doris Liu    int draw(Canvas* outCanvas, SkColorFilter* colorFilter,
5514bbc2931263b232fba61807fca00e127573eff42Doris Liu            const SkRect& bounds, bool needsMirroring, bool canReuseCache);
5521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void drawStaging(Canvas* canvas);
5534bbc2931263b232fba61807fca00e127573eff42Doris Liu
554fc9999505a36c66892d7ccce85187936105f4f36sergeyv    Bitmap& getBitmapUpdateIfDirty();
5554bbc2931263b232fba61807fca00e127573eff42Doris Liu    void setAllowCaching(bool allowCaching) {
5564bbc2931263b232fba61807fca00e127573eff42Doris Liu        mAllowCaching = allowCaching;
5574bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
558766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    SkPaint* getPaint();
5591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void syncProperties() {
5601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mNonAnimatablePropertiesDirty) {
5611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncNonAnimatableProperties(mStagingProperties);
5621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.mNonAnimatablePropertiesDirty = false;
5631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mAnimatablePropertiesDirty) {
5661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncAnimatableProperties(mStagingProperties);
5671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
5681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.syncAnimatableProperties(mProperties);
5691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mStagingProperties.mAnimatablePropertiesDirty = false;
5711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->syncProperties();
5721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class TreeProperties {
5751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
576a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit TreeProperties(Tree* tree) : mTree(tree) {}
5771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Properties that can only be modified by UI thread, therefore sync should
5781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // only go from UI to RT
5791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct NonAnimatableProperties {
5801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportWidth = 0;
5811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportHeight = 0;
5821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkRect bounds;
5831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledWidth = 0;
5841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledHeight = 0;
5851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColorFilter* colorFilter = nullptr;
5861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            ~NonAnimatableProperties() {
5871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkSafeUnref(colorFilter);
5881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } mNonAnimatableProperties;
5901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mNonAnimatablePropertiesDirty = true;
5911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float mRootAlpha = 1.0f;
5931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mAnimatablePropertiesDirty = true;
5941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncNonAnimatableProperties(const TreeProperties& prop) {
5961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Copy over the data that can only be changed in UI thread
5971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
5981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
5991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                        prop.mNonAnimatableProperties.colorFilter);
6001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mNonAnimatableProperties = prop.mNonAnimatableProperties;
6021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setViewportSize(float width, float height) {
6051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.viewportWidth != width
6061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                    || mNonAnimatableProperties.viewportHeight != height) {
6071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportWidth = width;
6091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportHeight = height;
6101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setBounds(const SkRect& bounds) {
6141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.bounds != bounds) {
6151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.bounds = bounds;
6161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaledSize(int width, int height) {
622037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // If the requested size is bigger than what the bitmap was, then
623037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // we increase the bitmap size to match. The width and height
624037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // are bound by MAX_CACHED_BITMAP_SIZE.
625037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            if (mNonAnimatableProperties.scaledWidth < width
626037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu                    || mNonAnimatableProperties.scaledHeight < height) {
627037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu                mNonAnimatableProperties.scaledWidth = std::max(width,
628037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu                        mNonAnimatableProperties.scaledWidth);
629037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu                mNonAnimatableProperties.scaledHeight = std::max(height,
630037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu                        mNonAnimatableProperties.scaledHeight);
6311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorFilter(SkColorFilter* filter) {
6361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
6371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        SkColorFilter* getColorFilter() const{
6421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.colorFilter;
6431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getViewportWidth() const {
6461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.viewportWidth;
6471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getViewportHeight() const {
6491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.viewportHeight;
6501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaledWidth() const {
6521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.scaledWidth;
6531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getScaledHeight() const {
6551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.scaledHeight;
6561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncAnimatableProperties(const TreeProperties& prop) {
6581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mRootAlpha = prop.mRootAlpha;
6591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool setRootAlpha(float rootAlpha) {
6611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (rootAlpha != mRootAlpha) {
6621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mAnimatablePropertiesDirty = true;
6631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mRootAlpha = rootAlpha;
6641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return true;
6661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return false;
6681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getRootAlpha() const { return mRootAlpha;}
6701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        const SkRect& getBounds() const {
6711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return mNonAnimatableProperties.bounds;
6721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Tree* mTree;
6741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
6751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onPropertyChanged(TreeProperties* prop);
6761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
677335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    const TreeProperties* stagingProperties() const { return &mStagingProperties; }
6781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
6801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateProperties() { return &mProperties; }
6814bbc2931263b232fba61807fca00e127573eff42Doris Liu
68223c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev    // called from RT only
68323c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev    const TreeProperties& properties() const { return mProperties; }
68423c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
68567ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    // This should always be called from RT.
6867c7052dd9bbfb2d98112975f7cbd2655212bf85bDoris Liu    void markDirty() { mCache.dirty = true; }
68767ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    bool isDirty() const { return mCache.dirty; }
68867ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; }
68967ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; }
69067ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu
6913310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    /**
6923310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * Draws VD cache into a canvas. This should always be called from RT and it works with Skia
6933310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * pipelines only.
6943310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     */
69523c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev    void draw(SkCanvas* canvas);
69623c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
6973310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    /**
6983310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * Draws VD into a GPU backed surface.
6993310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * This should always be called from RT and it works with Skia pipeline only.
7003310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     */
7013310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    void updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context);
70223c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
7034bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
7043310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    class Cache {
7053310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    public:
70623c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev        sk_sp<Bitmap> bitmap; //used by HWUI pipeline and software
70723c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev        //TODO: use surface instead of bitmap when drawing in software canvas
708fc9999505a36c66892d7ccce85187936105f4f36sergeyv        bool dirty = true;
7093310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7103310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        // the rest of the code in Cache is used by Skia pipelines only
7113310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7123310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        ~Cache() { clear(); }
7133310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7143310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
7153310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Stores a weak pointer to the atlas and a key.
7163310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
7173310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        void setAtlas(sp<skiapipeline::VectorDrawableAtlas> atlas,
7183310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev                skiapipeline::AtlasKey newAtlasKey);
7193310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7203310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
7213310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Gets a surface and bounds from the atlas.
7223310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         *
7233310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * @return nullptr if the altas has been deleted.
7243310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
7253310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        sk_sp<SkSurface> getSurface(SkRect* bounds);
7263310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7273310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
7283310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Releases atlas key from the atlas, which makes it available for reuse.
7293310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
7303310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        void clear();
7313310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    private:
7323310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        wp<skiapipeline::VectorDrawableAtlas> mAtlas;
7333310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY;
734fc9999505a36c66892d7ccce85187936105f4f36sergeyv    };
7351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
737fc9999505a36c66892d7ccce85187936105f4f36sergeyv    bool allocateBitmapIfNeeded(Cache& cache, int width, int height);
738fc9999505a36c66892d7ccce85187936105f4f36sergeyv    bool canReuseBitmap(Bitmap*, int width, int height);
739fc9999505a36c66892d7ccce85187936105f4f36sergeyv    void updateBitmapCache(Bitmap& outCache, bool useStagingData);
7403310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7413310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    /**
7423310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * Draws the root node into "surface" at a given "dst" position.
7433310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     */
7443310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    void draw(SkSurface* surface, const SkRect& dst);
7453310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
7464bbc2931263b232fba61807fca00e127573eff42Doris Liu    // Cap the bitmap size, such that it won't hurt the performance too much
7474bbc2931263b232fba61807fca00e127573eff42Doris Liu    // and it won't crash due to a very large scale.
7484bbc2931263b232fba61807fca00e127573eff42Doris Liu    // The drawable will look blurry above this size.
7494bbc2931263b232fba61807fca00e127573eff42Doris Liu    const static int MAX_CACHED_BITMAP_SIZE;
7504bbc2931263b232fba61807fca00e127573eff42Doris Liu
7514bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mAllowCaching = true;
752ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    std::unique_ptr<Group> mRootNode;
7531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mProperties = TreeProperties(this);
7551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mStagingProperties = TreeProperties(this);
7561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7574bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPaint mPaint;
7581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mStagingCache;
7601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mCache;
7614bbc2931263b232fba61807fca00e127573eff42Doris Liu
7621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener mPropertyChangedListener
7631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            = PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
76467ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu
76567ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    mutable bool mWillBeConsumed = false;
7664bbc2931263b232fba61807fca00e127573eff42Doris Liu};
7674bbc2931263b232fba61807fca00e127573eff42Doris Liu
7684bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace VectorDrawable
7694bbc2931263b232fba61807fca00e127573eff42Doris Liu
7704bbc2931263b232fba61807fca00e127573eff42Doris Liutypedef VectorDrawable::Path::Data PathData;
7714bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace uirenderer
7724bbc2931263b232fba61807fca00e127573eff42Doris Liu} // namespace android
7734bbc2931263b232fba61807fca00e127573eff42Doris Liu
7744bbc2931263b232fba61807fca00e127573eff42Doris Liu#endif // ANDROID_HWUI_VPATH_H
775