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