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
201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "DisplayList.h"
21fc9999505a36c66892d7ccce85187936105f4f36sergeyv#include "hwui/Bitmap.h"
221bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "hwui/Canvas.h"
233310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev#include "renderthread/CacheManager.h"
24766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
254bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkBitmap.h>
261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <SkCanvas.h>
274bbc2931263b232fba61807fca00e127573eff42Doris Liu#include <SkColor.h>
281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu#include <SkColorFilter.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 <string>
401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <vector>
414bbc2931263b232fba61807fca00e127573eff42Doris Liu
424bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace android {
434bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace uirenderer {
444bbc2931263b232fba61807fca00e127573eff42Doris Liu
4585d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu// Debug
4685d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#if DEBUG_VECTOR_DRAWABLE
471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define VECTOR_DRAWABLE_LOGD(...) ALOGD(__VA_ARGS__)
4885d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#else
491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define VECTOR_DRAWABLE_LOGD(...)
5085d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu#endif
5185d99528b23b5575d97f614fe25f839d19740abcTeng-Hui Zhu
524bbc2931263b232fba61807fca00e127573eff42Doris Liunamespace VectorDrawable {
531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define VD_SET_PRIMITIVE_FIELD_WITH_FLAG(field, value, flag) \
541bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    (VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, (value)) ? ((flag) = true, true) : false)
5532d7cda0b89a114171f14de0753674090b3d75fcDoris Liu#define VD_SET_PROP(field, value) ((value) != (field) ? ((field) = (value), true) : false)
561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(field, value)               \
571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ({                                                                \
581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        bool retVal = VD_SET_PROP((mPrimitiveFields.field), (value)); \
591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        onPropertyChanged();                                          \
601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        retVal;                                                       \
611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    })
621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define UPDATE_SKPROP(field, value)                                    \
631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ({                                                                 \
641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        bool retVal = ((field) != (value));                            \
651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        if ((field) != (value)) SkRefCnt_SafeAssign((field), (value)); \
661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        retVal;                                                        \
671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    })
684bbc2931263b232fba61807fca00e127573eff42Doris Liu
694bbc2931263b232fba61807fca00e127573eff42Doris Liu/* A VectorDrawable is composed of a tree of nodes.
704bbc2931263b232fba61807fca00e127573eff42Doris Liu * Each node can be a group node, or a path.
714bbc2931263b232fba61807fca00e127573eff42Doris Liu * A group node can have groups or paths as children, but a path node has
724bbc2931263b232fba61807fca00e127573eff42Doris Liu * no children.
734bbc2931263b232fba61807fca00e127573eff42Doris Liu * One example can be:
744bbc2931263b232fba61807fca00e127573eff42Doris Liu *                 Root Group
754bbc2931263b232fba61807fca00e127573eff42Doris Liu *                /    |     \
764bbc2931263b232fba61807fca00e127573eff42Doris Liu *           Group    Path    Group
774bbc2931263b232fba61807fca00e127573eff42Doris Liu *          /     \             |
784bbc2931263b232fba61807fca00e127573eff42Doris Liu *         Path   Path         Path
794bbc2931263b232fba61807fca00e127573eff42Doris Liu *
801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * VectorDrawables are drawn into bitmap caches first, then the caches are drawn to the given
811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * canvas with root alpha applied. Two caches are maintained for VD, one in UI thread, the other in
821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Render Thread. A generation id is used to keep track of changes in the vector drawable tree.
831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Each cache has their own generation id to track whether they are up to date with the latest
841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * change in the tree.
851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * Any property change to the vector drawable coming from UI thread (such as bulk setters to update
871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * all the properties, and viewport change, etc.) are only modifying the staging properties. The
881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties will then be marked dirty and will be pushed over to render thread properties
891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * at sync point. If staging properties are not dirty at sync point, we sync backwards by updating
901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu * staging properties with render thread properties to reflect the latest animation value.
911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu *
924bbc2931263b232fba61807fca00e127573eff42Doris Liu */
931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuclass PropertyChangedListener {
951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liupublic:
961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener(bool* dirty, bool* stagingDirty)
971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            : mDirty(dirty), mStagingDirty(stagingDirty) {}
981bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void onPropertyChanged() { *mDirty = true; }
991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void onStagingPropertyChanged() { *mStagingDirty = true; }
1001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
1011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
1021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mDirty;
1031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool* mStagingDirty;
1041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu};
1051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1064bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Node {
1074bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
1081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class Properties {
1091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
110a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit Properties(Node* node) : mNode(node) {}
1111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        inline void onPropertyChanged() { mNode->onPropertyChanged(this); }
1121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
1131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
1141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Node* mNode;
1151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    Node(const Node& node) { mName = node.mName; }
1174bbc2931263b232fba61807fca00e127573eff42Doris Liu    Node() {}
118cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual void draw(SkCanvas* outCanvas, bool useStagingData) = 0;
1194bbc2931263b232fba61807fca00e127573eff42Doris Liu    virtual void dump() = 0;
1201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void setName(const char* name) { mName = name; }
1211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void setPropertyChangedListener(PropertyChangedListener* listener) {
1221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mPropertyChangedListener = listener;
1231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) = 0;
1251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    virtual ~Node() {}
1261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() = 0;
1276b184d7a43d88511841407673448c64a114fdb4eDoris Liu    virtual void setAntiAlias(bool aa) = 0;
1281bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
1294bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
1304bbc2931263b232fba61807fca00e127573eff42Doris Liu    std::string mName;
1311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PropertyChangedListener* mPropertyChangedListener = nullptr;
1324bbc2931263b232fba61807fca00e127573eff42Doris Liu};
1334bbc2931263b232fba61807fca00e127573eff42Doris Liu
1344bbc2931263b232fba61807fca00e127573eff42Doris Liuclass ANDROID_API Path : public Node {
1354bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
1364bbc2931263b232fba61807fca00e127573eff42Doris Liu    struct ANDROID_API Data {
1374bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<char> verbs;
1384bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<size_t> verbSizes;
1394bbc2931263b232fba61807fca00e127573eff42Doris Liu        std::vector<float> points;
1404bbc2931263b232fba61807fca00e127573eff42Doris Liu        bool operator==(const Data& data) const {
1411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            return verbs == data.verbs && verbSizes == data.verbSizes && points == data.points;
1424bbc2931263b232fba61807fca00e127573eff42Doris Liu        }
1434bbc2931263b232fba61807fca00e127573eff42Doris Liu    };
1441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class PathProperties : public Properties {
1461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
147a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit PathProperties(Node* node) : Properties(node) {}
1481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const PathProperties& prop) {
1491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = prop.mData;
1501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setData(const Data& data) {
1531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Updates the path data. Note that we don't generate a new Skia path right away
1541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // because there are cases where the animation is changing the path data, but the view
1551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // that hosts the VD has gone off screen, in which case we won't even draw. So we
1561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // postpone the Skia path generation to the draw time.
1571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (data == mData) {
1581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return;
1591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mData = data;
1611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
1621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        const Data& getData() const { return mData; }
1641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
1651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
1661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Data mData;
1671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
1681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1694bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const Path& path);
1704bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path(const char* path, size_t strLength);
1714bbc2931263b232fba61807fca00e127573eff42Doris Liu    Path() {}
1721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1734bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
1741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
1751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* prop) override {
1761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (prop == &mStagingProperties) {
1771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
1781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
1801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        } else if (prop == &mProperties) {
1821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mSkPathDirty = true;
1831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
1841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
1851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
1861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
1871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
1881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateStagingProperties() { return &mStagingProperties; }
1891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const PathProperties* stagingProperties() { return &mStagingProperties; }
1901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
1921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties* mutateProperties() { return &mProperties; }
1934bbc2931263b232fba61807fca00e127573eff42Doris Liu
1944bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
195cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath);
1961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
1971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Internal data, render thread only.
1984bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mSkPathDirty = true;
1991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPath mSkPath;
2001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
2011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liuprivate:
2021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mProperties = PathProperties(this);
2031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    PathProperties mStagingProperties = PathProperties(this);
2041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
2054bbc2931263b232fba61807fca00e127573eff42Doris Liu};
2064bbc2931263b232fba61807fca00e127573eff42Doris Liu
2071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass ANDROID_API FullPath : public Path {
2084bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
2091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class FullPathProperties : public Properties {
2101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
2111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct PrimitiveFields {
2121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeWidth = 0;
2131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor strokeColor = SK_ColorTRANSPARENT;
2141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeAlpha = 1;
2151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColor fillColor = SK_ColorTRANSPARENT;
2161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float fillAlpha = 1;
2171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathStart = 0;
2181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathEnd = 1;
2191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float trimPathOffset = 0;
2201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
2211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
2221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float strokeMiterLimit = 4;
2231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int fillType = 0; /* non-zero or kWinding_FillType in Skia */
2241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
225a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit FullPathProperties(Node* mNode) : Properties(mNode), mTrimDirty(false) {}
226ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        ~FullPathProperties() {
227ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            SkSafeUnref(fillGradient);
228ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            SkSafeUnref(strokeGradient);
229ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        }
2301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const FullPathProperties& prop) {
2311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields = prop.mPrimitiveFields;
2321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
233ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            UPDATE_SKPROP(fillGradient, prop.fillGradient);
234ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu            UPDATE_SKPROP(strokeGradient, prop.strokeGradient);
2351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
2361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillGradient(SkShader* gradient) {
2381bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            if (UPDATE_SKPROP(fillGradient, gradient)) {
2391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeGradient(SkShader* gradient) {
2431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            if (UPDATE_SKPROP(strokeGradient, gradient)) {
2441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                onPropertyChanged();
2451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
2461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SkShader* getFillGradient() const { return fillGradient; }
2481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SkShader* getStrokeGradient() const { return strokeGradient; }
2491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getStrokeWidth() const { return mPrimitiveFields.strokeWidth; }
2501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeWidth(float strokeWidth) {
25132d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeWidth, strokeWidth);
2521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SkColor getStrokeColor() const { return mPrimitiveFields.strokeColor; }
2541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeColor(SkColor strokeColor) {
25532d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeColor, strokeColor);
2561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getStrokeAlpha() const { return mPrimitiveFields.strokeAlpha; }
2581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setStrokeAlpha(float strokeAlpha) {
25932d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(strokeAlpha, strokeAlpha);
2601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SkColor getFillColor() const { return mPrimitiveFields.fillColor; }
2621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillColor(SkColor fillColor) {
26332d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillColor, fillColor);
2641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getFillAlpha() const { return mPrimitiveFields.fillAlpha; }
2661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setFillAlpha(float fillAlpha) {
26732d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(fillAlpha, fillAlpha);
2681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getTrimPathStart() const { return mPrimitiveFields.trimPathStart; }
2701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathStart(float trimPathStart) {
27132d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathStart, trimPathStart, mTrimDirty);
2721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getTrimPathEnd() const { return mPrimitiveFields.trimPathEnd; }
2741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathEnd(float trimPathEnd) {
27532d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathEnd, trimPathEnd, mTrimDirty);
2761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
2771bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getTrimPathOffset() const { return mPrimitiveFields.trimPathOffset; }
2781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTrimPathOffset(float trimPathOffset) {
27932d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_WITH_FLAG(trimPathOffset, trimPathOffset, mTrimDirty);
2801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
281766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
2821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getStrokeMiterLimit() const { return mPrimitiveFields.strokeMiterLimit; }
2831bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getStrokeLineCap() const { return mPrimitiveFields.strokeLineCap; }
2841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getStrokeLineJoin() const { return mPrimitiveFields.strokeLineJoin; }
2851bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getFillType() const { return mPrimitiveFields.fillType; }
2861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool copyProperties(int8_t* outProperties, int length) const;
2871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void updateProperties(float strokeWidth, SkColor strokeColor, float strokeAlpha,
2881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                              SkColor fillColor, float fillAlpha, float trimPathStart,
2891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                              float trimPathEnd, float trimPathOffset, float strokeMiterLimit,
2901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                              int strokeLineCap, int strokeLineJoin, int fillType) {
2911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeWidth = strokeWidth;
2921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeColor = strokeColor;
2931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeAlpha = strokeAlpha;
2941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillColor = fillColor;
2951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillAlpha = fillAlpha;
2961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathStart = trimPathStart;
2971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathEnd = trimPathEnd;
2981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.trimPathOffset = trimPathOffset;
2991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeMiterLimit = strokeMiterLimit;
3001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineCap = strokeLineCap;
3011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.strokeLineJoin = strokeLineJoin;
3021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.fillType = fillType;
3031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mTrimDirty = true;
3041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
3051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Set property values during animation
3071d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorPropertyValue(int propertyId, int32_t value);
3081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPropertyValue(int propertyId, float value);
3091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mTrimDirty;
3101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
3111d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
3121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        enum class Property {
3131d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeWidth = 0,
3141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeColor,
3151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeAlpha,
3161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillColor,
3171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillAlpha,
3181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathStart,
3191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathEnd,
3201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            trimPathOffset,
3211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineCap,
3221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeLineJoin,
3231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            strokeMiterLimit,
3241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            fillType,
3251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            count,
3261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
3271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        PrimitiveFields mPrimitiveFields;
328ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        SkShader* fillGradient = nullptr;
329ad21fe27627c8f4a1de886a2d1c5296694dc3501Doris Liu        SkShader* strokeGradient = nullptr;
3301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
331766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu
3321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Called from UI thread
3331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    FullPath(const FullPath& path);  // for cloning
3344bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
3354bbc2931263b232fba61807fca00e127573eff42Doris Liu    FullPath() : Path() {}
336cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    void draw(SkCanvas* outCanvas, bool useStagingData) override;
3371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void dump() override;
3381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateStagingProperties() { return &mStagingProperties; }
3391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const FullPathProperties* stagingProperties() { return &mStagingProperties; }
3401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
3421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties* mutateProperties() { return &mProperties; }
3431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
3451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
3461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Path::onPropertyChanged(properties);
3471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
3481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
3491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
3511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else if (properties == &mProperties) {
3531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
3541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
3551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
3561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
3574bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
3586b184d7a43d88511841407673448c64a114fdb4eDoris Liu    virtual void setAntiAlias(bool aa) { mAntiAlias = aa; }
359dbee9bb342cdfaa5155b1918f90262c05e2464cbTeng-Hui Zhu
3604bbc2931263b232fba61807fca00e127573eff42Doris Liuprotected:
361cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    const SkPath& getUpdatedPath(bool useStagingData, SkPath* tempStagingPath) override;
3621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckprivate:
3641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mProperties = FullPathProperties(this);
3651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    FullPathProperties mStagingProperties = FullPathProperties(this);
3661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
3671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
3681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Intermediate data for drawing, render thread only
3694bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPath mTrimmedSkPath;
3706b184d7a43d88511841407673448c64a114fdb4eDoris Liu    // Default to use AntiAlias
3716b184d7a43d88511841407673448c64a114fdb4eDoris Liu    bool mAntiAlias = true;
3724bbc2931263b232fba61807fca00e127573eff42Doris Liu};
3734bbc2931263b232fba61807fca00e127573eff42Doris Liu
3741bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass ANDROID_API ClipPath : public Path {
3754bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
3764bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const ClipPath& path) : Path(path) {}
3774bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
3784bbc2931263b232fba61807fca00e127573eff42Doris Liu    ClipPath() : Path() {}
379cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    void draw(SkCanvas* outCanvas, bool useStagingData) override;
3806b184d7a43d88511841407673448c64a114fdb4eDoris Liu    virtual void setAntiAlias(bool aa) {}
3814bbc2931263b232fba61807fca00e127573eff42Doris Liu};
3824bbc2931263b232fba61807fca00e127573eff42Doris Liu
3831bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckclass ANDROID_API Group : public Node {
3844bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
3851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class GroupProperties : public Properties {
3861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
387a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit GroupProperties(Node* mNode) : Properties(mNode) {}
3881d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct PrimitiveFields {
3891d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float rotate = 0;
3901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float pivotX = 0;
3911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float pivotY = 0;
3921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleX = 1;
3931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float scaleY = 1;
3941d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float translateX = 0;
3951d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float translateY = 0;
3961d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } mPrimitiveFields;
3971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncProperties(const GroupProperties& prop) {
3981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields = prop.mPrimitiveFields;
3991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
4001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getRotation() const { return mPrimitiveFields.rotate; }
4021bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setRotation(float rotation) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(rotate, rotation); }
4031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getPivotX() const { return mPrimitiveFields.pivotX; }
4041bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setPivotX(float pivotX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotX, pivotX); }
4051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getPivotY() const { return mPrimitiveFields.pivotY; }
4061bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setPivotY(float pivotY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(pivotY, pivotY); }
4071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getScaleX() const { return mPrimitiveFields.scaleX; }
4081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setScaleX(float scaleX) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleX, scaleX); }
4091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getScaleY() const { return mPrimitiveFields.scaleY; }
4101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setScaleY(float scaleY) { VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(scaleY, scaleY); }
4111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getTranslateX() const { return mPrimitiveFields.translateX; }
4121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateX(float translateX) {
41332d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateX, translateX);
4141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getTranslateY() const { return mPrimitiveFields.translateY; }
4161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setTranslateY(float translateY) {
41732d7cda0b89a114171f14de0753674090b3d75fcDoris Liu            VD_SET_PRIMITIVE_FIELD_AND_NOTIFY(translateY, translateY);
4181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void updateProperties(float rotate, float pivotX, float pivotY, float scaleX, float scaleY,
4201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                              float translateX, float translateY) {
4211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.rotate = rotate;
4221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.pivotX = pivotX;
4231d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.pivotY = pivotY;
4241d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.scaleX = scaleX;
4251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.scaleY = scaleY;
4261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.translateX = translateX;
4271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mPrimitiveFields.translateY = translateY;
4281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            onPropertyChanged();
4291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setPropertyValue(int propertyId, float value);
4311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float getPropertyValue(int propertyId) const;
4321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool copyProperties(float* outProperties, int length) const;
4331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        static bool isValidProperty(int propertyId);
4341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
4351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    private:
4361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        enum class Property {
4371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            rotate = 0,
4381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            pivotX,
4391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            pivotY,
4401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            scaleX,
4411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            scaleY,
4421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            translateX,
4431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            translateY,
4441d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Count of the properties, must be at the end.
4451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            count,
4461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        };
447766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    };
4481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
4494bbc2931263b232fba61807fca00e127573eff42Doris Liu    Group(const Group& group);
4504bbc2931263b232fba61807fca00e127573eff42Doris Liu    Group() {}
4511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void addChild(Node* child);
4521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void setPropertyChangedListener(PropertyChangedListener* listener) override {
4531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Node::setPropertyChangedListener(listener);
4541d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        for (auto& child : mChildren) {
4551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            child->setPropertyChangedListener(listener);
4561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4574bbc2931263b232fba61807fca00e127573eff42Doris Liu    }
4581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void syncProperties() override;
4591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties* mutateStagingProperties() { return &mStagingProperties; }
4601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    const GroupProperties* stagingProperties() { return &mStagingProperties; }
4611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
4621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
4631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties* mutateProperties() { return &mProperties; }
4641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
4651d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // Methods below could be called from either UI thread or Render Thread.
466cc29a5dde1ef0a3cf0fcec10eb9d37d9e8fa3afbStan Iliev    virtual void draw(SkCanvas* outCanvas, bool useStagingData) override;
4671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void getLocalMatrix(SkMatrix* outMatrix, const GroupProperties& properties);
4684bbc2931263b232fba61807fca00e127573eff42Doris Liu    void dump() override;
469766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    static bool isValidProperty(int propertyId);
4704bbc2931263b232fba61807fca00e127573eff42Doris Liu
4711d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    virtual void onPropertyChanged(Properties* properties) override {
4721d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (properties == &mStagingProperties) {
4731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingPropertiesDirty = true;
4741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
4751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onStagingPropertyChanged();
4761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
4771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
4781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mPropertyChangedListener) {
4791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mPropertyChangedListener->onPropertyChanged();
4801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
4811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
4821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
4831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
4846b184d7a43d88511841407673448c64a114fdb4eDoris Liu    virtual void setAntiAlias(bool aa) {
4856b184d7a43d88511841407673448c64a114fdb4eDoris Liu        for (auto& child : mChildren) {
4866b184d7a43d88511841407673448c64a114fdb4eDoris Liu            child->setAntiAlias(aa);
4876b184d7a43d88511841407673448c64a114fdb4eDoris Liu        }
4886b184d7a43d88511841407673448c64a114fdb4eDoris Liu    }
4896b184d7a43d88511841407673448c64a114fdb4eDoris Liu
4904bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
4911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mProperties = GroupProperties(this);
4921d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    GroupProperties mStagingProperties = GroupProperties(this);
4931d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    bool mStagingPropertiesDirty = true;
4941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    std::vector<std::unique_ptr<Node> > mChildren;
4954bbc2931263b232fba61807fca00e127573eff42Doris Liu};
4964bbc2931263b232fba61807fca00e127573eff42Doris Liu
497766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liuclass ANDROID_API Tree : public VirtualLightRefBase {
4984bbc2931263b232fba61807fca00e127573eff42Doris Liupublic:
499a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh    explicit Tree(Group* rootNode) : mRootNode(rootNode) {
5001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->setPropertyChangedListener(&mPropertyChangedListener);
5011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
502335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu
503335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    // Copy properties from the tree and use the give node as the root node
504335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    Tree(const Tree* copy, Group* rootNode) : Tree(rootNode) {
505335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu        mStagingProperties.syncAnimatableProperties(*copy->stagingProperties());
506335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu        mStagingProperties.syncNonAnimatableProperties(*copy->stagingProperties());
507335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    }
508f8d131cc8dc4ef675b8f8fc57dcc26062d575d32Doris Liu    // Draws the VD onto a bitmap cache, then the bitmap cache will be rendered onto the input
509f8d131cc8dc4ef675b8f8fc57dcc26062d575d32Doris Liu    // canvas. Returns the number of pixels needed for the bitmap cache.
5101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    int draw(Canvas* outCanvas, SkColorFilter* colorFilter, const SkRect& bounds,
5111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck             bool needsMirroring, bool canReuseCache);
5121d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void drawStaging(Canvas* canvas);
5134bbc2931263b232fba61807fca00e127573eff42Doris Liu
514fc9999505a36c66892d7ccce85187936105f4f36sergeyv    Bitmap& getBitmapUpdateIfDirty();
5151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void setAllowCaching(bool allowCaching) { mAllowCaching = allowCaching; }
516766431aa57c16ece8842287a92b2e7208e3b8ac3Doris Liu    SkPaint* getPaint();
5171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void syncProperties() {
5181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mNonAnimatablePropertiesDirty) {
5191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            mCache.dirty |= (mProperties.mNonAnimatableProperties.viewportWidth !=
5201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             mStagingProperties.mNonAnimatableProperties.viewportWidth) ||
5211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                            (mProperties.mNonAnimatableProperties.viewportHeight !=
5221bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             mStagingProperties.mNonAnimatableProperties.viewportHeight) ||
5231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                            (mProperties.mNonAnimatableProperties.scaledWidth !=
5241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             mStagingProperties.mNonAnimatableProperties.scaledWidth) ||
5251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                            (mProperties.mNonAnimatableProperties.scaledHeight !=
5261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             mStagingProperties.mNonAnimatableProperties.scaledHeight) ||
5271bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                            (mProperties.mNonAnimatableProperties.bounds !=
5281bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                             mStagingProperties.mNonAnimatableProperties.bounds);
5291d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncNonAnimatableProperties(mStagingProperties);
5301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.mNonAnimatablePropertiesDirty = false;
5311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5331d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        if (mStagingProperties.mAnimatablePropertiesDirty) {
5341d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mProperties.syncAnimatableProperties(mStagingProperties);
5351d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } else {
5361d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mStagingProperties.syncAnimatableProperties(mProperties);
5371d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5381d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mStagingProperties.mAnimatablePropertiesDirty = false;
5391d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        mRootNode->syncProperties();
5401d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    }
5411d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5421d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    class TreeProperties {
5431d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    public:
544a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit TreeProperties(Tree* tree) : mTree(tree) {}
5451d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // Properties that can only be modified by UI thread, therefore sync should
5461d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        // only go from UI to RT
5471d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        struct NonAnimatableProperties {
5481d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportWidth = 0;
5491d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            float viewportHeight = 0;
5501d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkRect bounds;
5511d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledWidth = 0;
5521d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            int scaledHeight = 0;
5531d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            SkColorFilter* colorFilter = nullptr;
5541bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            ~NonAnimatableProperties() { SkSafeUnref(colorFilter); }
5551d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        } mNonAnimatableProperties;
5561d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mNonAnimatablePropertiesDirty = true;
5571d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5581d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        float mRootAlpha = 1.0f;
5591d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool mAnimatablePropertiesDirty = true;
5601d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5611d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void syncNonAnimatableProperties(const TreeProperties& prop) {
5621d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            // Copy over the data that can only be changed in UI thread
5631d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.colorFilter != prop.mNonAnimatableProperties.colorFilter) {
5641d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                SkRefCnt_SafeAssign(mNonAnimatableProperties.colorFilter,
5651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                    prop.mNonAnimatableProperties.colorFilter);
5661d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5671d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            mNonAnimatableProperties = prop.mNonAnimatableProperties;
5681d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5691d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5701d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setViewportSize(float width, float height) {
5711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            if (mNonAnimatableProperties.viewportWidth != width ||
5721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                mNonAnimatableProperties.viewportHeight != height) {
5731d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
5741d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportWidth = width;
5751d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.viewportHeight = height;
5761d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
5771d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5781d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5791d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setBounds(const SkRect& bounds) {
5801d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (mNonAnimatableProperties.bounds != bounds) {
5811d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatableProperties.bounds = bounds;
5821d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
5831d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
5841d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
5851d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
5861d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
5871d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setScaledSize(int width, int height) {
588037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // If the requested size is bigger than what the bitmap was, then
589037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // we increase the bitmap size to match. The width and height
590037fc1815b0f69b0b24e68e16281b490bdeb1d56Teng-Hui Zhu            // are bound by MAX_CACHED_BITMAP_SIZE.
5911bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            if (mNonAnimatableProperties.scaledWidth < width ||
5921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                mNonAnimatableProperties.scaledHeight < height) {
5931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                mNonAnimatableProperties.scaledWidth =
5941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        std::max(width, mNonAnimatableProperties.scaledWidth);
5951bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                mNonAnimatableProperties.scaledHeight =
5961bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        std::max(height, mNonAnimatableProperties.scaledHeight);
5971d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
5981d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
5991d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6001d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6011d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        void setColorFilter(SkColorFilter* filter) {
6021d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (UPDATE_SKPROP(mNonAnimatableProperties.colorFilter, filter)) {
6031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mNonAnimatablePropertiesDirty = true;
6041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SkColorFilter* getColorFilter() const { return mNonAnimatableProperties.colorFilter; }
6081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getViewportWidth() const { return mNonAnimatableProperties.viewportWidth; }
6101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getViewportHeight() const { return mNonAnimatableProperties.viewportHeight; }
6111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getScaledWidth() const { return mNonAnimatableProperties.scaledWidth; }
6121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getScaledHeight() const { return mNonAnimatableProperties.scaledHeight; }
6131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void syncAnimatableProperties(const TreeProperties& prop) { mRootAlpha = prop.mRootAlpha; }
6141d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        bool setRootAlpha(float rootAlpha) {
6151d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            if (rootAlpha != mRootAlpha) {
6161d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mAnimatablePropertiesDirty = true;
6171d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mRootAlpha = rootAlpha;
6181d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                mTree->onPropertyChanged(this);
6191d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu                return true;
6201d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            }
6211d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu            return false;
6221d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        }
6231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        float getRootAlpha() const { return mRootAlpha; }
6241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        const SkRect& getBounds() const { return mNonAnimatableProperties.bounds; }
6251d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu        Tree* mTree;
6261d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    };
6271d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    void onPropertyChanged(TreeProperties* prop);
6281d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateStagingProperties() { return &mStagingProperties; }
629335d7d174464ea3fc2d058dcff6e436df1cf0fd9Doris Liu    const TreeProperties* stagingProperties() const { return &mStagingProperties; }
6301d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6311d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    // This should only be called from animations on RT
6321d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties* mutateProperties() { return &mProperties; }
6334bbc2931263b232fba61807fca00e127573eff42Doris Liu
63423c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev    // called from RT only
63523c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev    const TreeProperties& properties() const { return mProperties; }
63623c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
63767ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    // This should always be called from RT.
6387c7052dd9bbfb2d98112975f7cbd2655212bf85bDoris Liu    void markDirty() { mCache.dirty = true; }
63967ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    bool isDirty() const { return mCache.dirty; }
64067ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    bool getPropertyChangeWillBeConsumed() const { return mWillBeConsumed; }
64167ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    void setPropertyChangeWillBeConsumed(bool willBeConsumed) { mWillBeConsumed = willBeConsumed; }
64267ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu
6433310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    /**
6443310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * Draws VD cache into a canvas. This should always be called from RT and it works with Skia
6453310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * pipelines only.
6463310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     */
64765e678fdb1375fe183e628ff158f66b2f04331d0Stan Iliev    void draw(SkCanvas* canvas, const SkRect& bounds);
64823c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
6493310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    /**
6503310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * Draws VD into a GPU backed surface.
6513310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     * This should always be called from RT and it works with Skia pipeline only.
6523310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev     */
6533310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    void updateCache(sp<skiapipeline::VectorDrawableAtlas>& atlas, GrContext* context);
65423c38a9ed9c28a9fda438e7d30532aad7a3844f7Stan Iliev
6556b184d7a43d88511841407673448c64a114fdb4eDoris Liu    void setAntiAlias(bool aa) { mRootNode->setAntiAlias(aa); }
6566b184d7a43d88511841407673448c64a114fdb4eDoris Liu
6574bbc2931263b232fba61807fca00e127573eff42Doris Liuprivate:
6583310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    class Cache {
6593310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    public:
6601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        sk_sp<Bitmap> bitmap;  // used by HWUI pipeline and software
6611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        // TODO: use surface instead of bitmap when drawing in software canvas
662fc9999505a36c66892d7ccce85187936105f4f36sergeyv        bool dirty = true;
6633310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6643310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        // the rest of the code in Cache is used by Skia pipelines only
6653310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6663310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        ~Cache() { clear(); }
6673310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6683310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
6693310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Stores a weak pointer to the atlas and a key.
6703310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
6713310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        void setAtlas(sp<skiapipeline::VectorDrawableAtlas> atlas,
6721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                      skiapipeline::AtlasKey newAtlasKey);
6733310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6743310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
6753310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Gets a surface and bounds from the atlas.
6763310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         *
6773310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * @return nullptr if the altas has been deleted.
6783310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
6793310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        sk_sp<SkSurface> getSurface(SkRect* bounds);
6803310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6813310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        /**
6823310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         * Releases atlas key from the atlas, which makes it available for reuse.
6833310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev         */
6843310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        void clear();
6851bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
6863310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev    private:
6873310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        wp<skiapipeline::VectorDrawableAtlas> mAtlas;
6883310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev        skiapipeline::AtlasKey mAtlasKey = INVALID_ATLAS_KEY;
689fc9999505a36c66892d7ccce85187936105f4f36sergeyv    };
6901d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
6911d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    SkPaint* updatePaint(SkPaint* outPaint, TreeProperties* prop);
692fc9999505a36c66892d7ccce85187936105f4f36sergeyv    bool allocateBitmapIfNeeded(Cache& cache, int width, int height);
693fc9999505a36c66892d7ccce85187936105f4f36sergeyv    bool canReuseBitmap(Bitmap*, int width, int height);
694fc9999505a36c66892d7ccce85187936105f4f36sergeyv    void updateBitmapCache(Bitmap& outCache, bool useStagingData);
6953310fb1b24c6cdd0781674fab69e359caf9d17e5Stan Iliev
6964bbc2931263b232fba61807fca00e127573eff42Doris Liu    // Cap the bitmap size, such that it won't hurt the performance too much
6974bbc2931263b232fba61807fca00e127573eff42Doris Liu    // and it won't crash due to a very large scale.
6984bbc2931263b232fba61807fca00e127573eff42Doris Liu    // The drawable will look blurry above this size.
6994bbc2931263b232fba61807fca00e127573eff42Doris Liu    const static int MAX_CACHED_BITMAP_SIZE;
7004bbc2931263b232fba61807fca00e127573eff42Doris Liu
7014bbc2931263b232fba61807fca00e127573eff42Doris Liu    bool mAllowCaching = true;
702ef062ebd20032efe697741d6c3dfd1faec54f590Doris Liu    std::unique_ptr<Group> mRootNode;
7031d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7041d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mProperties = TreeProperties(this);
7051d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    TreeProperties mStagingProperties = TreeProperties(this);
7061d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7074bbc2931263b232fba61807fca00e127573eff42Doris Liu    SkPaint mPaint;
7081d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu
7091d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mStagingCache;
7101d8e194661085f9a18ab1b3cd12f9e19d3a86be5Doris Liu    Cache mCache;
7114bbc2931263b232fba61807fca00e127573eff42Doris Liu
7121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    PropertyChangedListener mPropertyChangedListener =
7131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            PropertyChangedListener(&mCache.dirty, &mStagingCache.dirty);
71467ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu
71567ce99b66ebc816ae8bbc222db8f3695fb15495bDoris Liu    mutable bool mWillBeConsumed = false;
7164bbc2931263b232fba61807fca00e127573eff42Doris Liu};
7174bbc2931263b232fba61807fca00e127573eff42Doris Liu
7181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}  // namespace VectorDrawable
7194bbc2931263b232fba61807fca00e127573eff42Doris Liu
7204bbc2931263b232fba61807fca00e127573eff42Doris Liutypedef VectorDrawable::Path::Data PathData;
7211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}  // namespace uirenderer
7221bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}  // namespace android
7234bbc2931263b232fba61807fca00e127573eff42Doris Liu
7241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#endif  // ANDROID_HWUI_VPATH_H
725