VectorDrawable.h revision c2de46fadd4ca9c6aa2d9dd7a65b161b28fc6f3b
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_VPATH_H
18#define ANDROID_HWUI_VPATH_H
19
20#include "Canvas.h"
21#include <SkBitmap.h>
22#include <SkColor.h>
23#include <SkCanvas.h>
24#include <SkMatrix.h>
25#include <SkPaint.h>
26#include <SkPath.h>
27#include <SkPathMeasure.h>
28#include <SkRect.h>
29
30#include <cutils/compiler.h>
31#include <stddef.h>
32#include <vector>
33#include <string>
34
35namespace android {
36namespace uirenderer {
37
38namespace VectorDrawable {
39#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP(field, value) ? (flag = true, true): false);
40#define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
41
42/* A VectorDrawable is composed of a tree of nodes.
43 * Each node can be a group node, or a path.
44 * A group node can have groups or paths as children, but a path node has
45 * no children.
46 * One example can be:
47 *                 Root Group
48 *                /    |     \
49 *           Group    Path    Group
50 *          /     \             |
51 *         Path   Path         Path
52 *
53 */
54class ANDROID_API Node {
55public:
56    Node(const Node& node) {
57        mName = node.mName;
58    }
59    Node() {}
60    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
61            float scaleX, float scaleY) = 0;
62    virtual void dump() = 0;
63    void setName(const char* name) {
64        mName = name;
65    }
66    virtual ~Node(){}
67protected:
68    std::string mName;
69};
70
71class ANDROID_API Path : public Node {
72public:
73    struct ANDROID_API Data {
74        std::vector<char> verbs;
75        std::vector<size_t> verbSizes;
76        std::vector<float> points;
77        bool operator==(const Data& data) const {
78            return verbs == data.verbs && verbSizes == data.verbSizes
79                    && points == data.points;
80        }
81    };
82    Path(const Data& nodes);
83    Path(const Path& path);
84    Path(const char* path, size_t strLength);
85    Path() {}
86    void dump() override;
87    bool canMorph(const Data& path);
88    bool canMorph(const Path& path);
89    void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
90            float scaleX, float scaleY) override;
91    void setPath(const char* path, size_t strLength);
92    void setPathData(const Data& data);
93    static float getMatrixScale(const SkMatrix& groupStackedMatrix);
94
95protected:
96    virtual const SkPath& getUpdatedPath();
97    virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
98            float strokeScale) = 0;
99    Data mData;
100    SkPath mSkPath;
101    bool mSkPathDirty = true;
102};
103
104class ANDROID_API FullPath: public Path {
105public:
106    FullPath(const FullPath& path); // for cloning
107    FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
108    FullPath() : Path() {}
109    FullPath(const Data& nodes) : Path(nodes) {}
110
111    void updateProperties(float strokeWidth, SkColor strokeColor,
112            float strokeAlpha, SkColor fillColor, float fillAlpha,
113            float trimPathStart, float trimPathEnd, float trimPathOffset,
114            float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
115    float getStrokeWidth() {
116        return mStrokeWidth;
117    }
118    void setStrokeWidth(float strokeWidth) {
119        mStrokeWidth = strokeWidth;
120    }
121    SkColor getStrokeColor() {
122        return mStrokeColor;
123    }
124    void setStrokeColor(SkColor strokeColor) {
125        mStrokeColor = strokeColor;
126    }
127    float getStrokeAlpha() {
128        return mStrokeAlpha;
129    }
130    void setStrokeAlpha(float strokeAlpha) {
131        mStrokeAlpha = strokeAlpha;
132    }
133    SkColor getFillColor() {
134        return mFillColor;
135    }
136    void setFillColor(SkColor fillColor) {
137        mFillColor = fillColor;
138    }
139    float getFillAlpha() {
140        return mFillAlpha;
141    }
142    void setFillAlpha(float fillAlpha) {
143        mFillAlpha = fillAlpha;
144    }
145    float getTrimPathStart() {
146        return mTrimPathStart;
147    }
148    void setTrimPathStart(float trimPathStart) {
149        VD_SET_PROP_WITH_FLAG(mTrimPathStart, trimPathStart, mTrimDirty);
150    }
151    float getTrimPathEnd() {
152        return mTrimPathEnd;
153    }
154    void setTrimPathEnd(float trimPathEnd) {
155        VD_SET_PROP_WITH_FLAG(mTrimPathEnd, trimPathEnd, mTrimDirty);
156    }
157    float getTrimPathOffset() {
158        return mTrimPathOffset;
159    }
160    void setTrimPathOffset(float trimPathOffset) {
161        VD_SET_PROP_WITH_FLAG(mTrimPathOffset, trimPathOffset, mTrimDirty);
162    }
163    bool getProperties(int8_t* outProperties, int length);
164
165protected:
166    const SkPath& getUpdatedPath() override;
167    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
168            float strokeScale) override;
169
170private:
171    // Applies trimming to the specified path.
172    void applyTrim();
173    float mStrokeWidth = 0;
174    SkColor mStrokeColor = SK_ColorTRANSPARENT;
175    float mStrokeAlpha = 1;
176    SkColor mFillColor = SK_ColorTRANSPARENT;
177    float mFillAlpha = 1;
178    float mTrimPathStart = 0;
179    float mTrimPathEnd = 1;
180    float mTrimPathOffset = 0;
181    bool mTrimDirty = true;
182    SkPaint::Cap mStrokeLineCap = SkPaint::Cap::kButt_Cap;
183    SkPaint::Join mStrokeLineJoin = SkPaint::Join::kMiter_Join;
184    float mStrokeMiterLimit = 4;
185    SkPath mTrimmedSkPath;
186    SkPaint mPaint;
187};
188
189class ANDROID_API ClipPath: public Path {
190public:
191    ClipPath(const ClipPath& path) : Path(path) {}
192    ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
193    ClipPath() : Path() {}
194    ClipPath(const Data& nodes) : Path(nodes) {}
195
196protected:
197    void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
198            float strokeScale) override;
199};
200
201class ANDROID_API Group: public Node {
202public:
203    Group(const Group& group);
204    Group() {}
205    float getRotation() {
206        return mRotate;
207    }
208    void setRotation(float rotation) {
209        mRotate = rotation;
210    }
211    float getPivotX() {
212        return mPivotX;
213    }
214    void setPivotX(float pivotX) {
215        mPivotX = pivotX;
216    }
217    float getPivotY() {
218        return mPivotY;
219    }
220    void setPivotY(float pivotY) {
221        mPivotY = pivotY;
222    }
223    float getScaleX() {
224        return mScaleX;
225    }
226    void setScaleX(float scaleX) {
227        mScaleX = scaleX;
228    }
229    float getScaleY() {
230        return mScaleY;
231    }
232    void setScaleY(float scaleY) {
233        mScaleY = scaleY;
234    }
235    float getTranslateX() {
236        return mTranslateX;
237    }
238    void setTranslateX(float translateX) {
239        mTranslateX = translateX;
240    }
241    float getTranslateY() {
242        return mTranslateY;
243    }
244    void setTranslateY(float translateY) {
245        mTranslateY = translateY;
246    }
247    virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
248            float scaleX, float scaleY) override;
249    void updateLocalMatrix(float rotate, float pivotX, float pivotY,
250            float scaleX, float scaleY, float translateX, float translateY);
251    void getLocalMatrix(SkMatrix* outMatrix);
252    void addChild(Node* child);
253    void dump() override;
254    bool getProperties(float* outProperties, int length);
255
256private:
257    enum class Property {
258        Rotate_Property = 0,
259        PivotX_Property,
260        PivotY_Property,
261        ScaleX_Property,
262        ScaleY_Property,
263        TranslateX_Property,
264        TranslateY_Property,
265        // Count of the properties, must be at the end.
266        Count,
267    };
268    float mRotate = 0;
269    float mPivotX = 0;
270    float mPivotY = 0;
271    float mScaleX = 1;
272    float mScaleY = 1;
273    float mTranslateX = 0;
274    float mTranslateY = 0;
275    std::vector<Node*> mChildren;
276};
277
278class ANDROID_API Tree {
279public:
280    Tree(Group* rootNode) : mRootNode(rootNode) {}
281    void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
282            const SkRect& bounds, bool needsMirroring, bool canReuseCache);
283    void drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
284            const SkRect& originalBounds);
285
286    void updateCachedBitmap(int width, int height);
287    void createCachedBitmapIfNeeded(int width, int height);
288    bool canReuseBitmap(int width, int height);
289    void setAllowCaching(bool allowCaching) {
290        mAllowCaching = allowCaching;
291    }
292    bool setRootAlpha(float rootAlpha) {
293        return VD_SET_PROP(mRootAlpha, rootAlpha);
294    }
295
296    float getRootAlpha() {
297        return mRootAlpha;
298    }
299    void setViewportSize(float viewportWidth, float viewportHeight) {
300        mViewportWidth = viewportWidth;
301        mViewportHeight = viewportHeight;
302    }
303
304private:
305    // Cap the bitmap size, such that it won't hurt the performance too much
306    // and it won't crash due to a very large scale.
307    // The drawable will look blurry above this size.
308    const static int MAX_CACHED_BITMAP_SIZE;
309
310    bool mCacheDirty = true;
311    bool mAllowCaching = true;
312    float mViewportWidth = 0;
313    float mViewportHeight = 0;
314    float mRootAlpha = 1.0f;
315
316    Group* mRootNode;
317    SkRect mBounds;
318    SkMatrix mCanvasMatrix;
319    SkPaint mPaint;
320    SkPathMeasure mPathMeasure;
321    SkBitmap mCachedBitmap;
322
323};
324
325} // namespace VectorDrawable
326
327typedef VectorDrawable::Path::Data PathData;
328} // namespace uirenderer
329} // namespace android
330
331#endif // ANDROID_HWUI_VPATH_H
332