blob: 09bdce596a2187baaf4683bfa3202b8bfc096a4e [file] [log] [blame]
Doris Liu4bbc2932015-12-01 17:59:40 -08001/*
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>
Doris Liuc2de46f2016-01-21 12:55:54 -080023#include <SkCanvas.h>
Doris Liu4bbc2932015-12-01 17:59:40 -080024#include <SkMatrix.h>
25#include <SkPaint.h>
26#include <SkPath.h>
27#include <SkPathMeasure.h>
28#include <SkRect.h>
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -080029#include <SkShader.h>
Doris Liu4bbc2932015-12-01 17:59:40 -080030
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() {}
Doris Liuc2de46f2016-01-21 12:55:54 -080061 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080062 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);
Doris Liuc2de46f2016-01-21 12:55:54 -080090 void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080091 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();
Doris Liuc2de46f2016-01-21 12:55:54 -080098 virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -080099 float strokeScale, const SkMatrix& matrix) = 0;
Doris Liu4bbc2932015-12-01 17:59:40 -0800100 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
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800112 ~FullPath() {
113 SkSafeUnref(mFillGradient);
114 SkSafeUnref(mStrokeGradient);
115 }
116
Doris Liu4bbc2932015-12-01 17:59:40 -0800117 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() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000122 return mStrokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800123 }
124 void setStrokeWidth(float strokeWidth) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000125 mStrokeWidth = strokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800126 }
127 SkColor getStrokeColor() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000128 return mStrokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800129 }
130 void setStrokeColor(SkColor strokeColor) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000131 mStrokeColor = strokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800132 }
133 float getStrokeAlpha() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000134 return mStrokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800135 }
136 void setStrokeAlpha(float strokeAlpha) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000137 mStrokeAlpha = strokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800138 }
139 SkColor getFillColor() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000140 return mFillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800141 }
142 void setFillColor(SkColor fillColor) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000143 mFillColor = fillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800144 }
145 float getFillAlpha() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000146 return mFillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800147 }
148 void setFillAlpha(float fillAlpha) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000149 mFillAlpha = fillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800150 }
151 float getTrimPathStart() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000152 return mTrimPathStart;
Doris Liu4bbc2932015-12-01 17:59:40 -0800153 }
154 void setTrimPathStart(float trimPathStart) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000155 VD_SET_PROP_WITH_FLAG(mTrimPathStart, trimPathStart, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800156 }
157 float getTrimPathEnd() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000158 return mTrimPathEnd;
Doris Liu4bbc2932015-12-01 17:59:40 -0800159 }
160 void setTrimPathEnd(float trimPathEnd) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000161 VD_SET_PROP_WITH_FLAG(mTrimPathEnd, trimPathEnd, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800162 }
163 float getTrimPathOffset() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000164 return mTrimPathOffset;
Doris Liu4bbc2932015-12-01 17:59:40 -0800165 }
166 void setTrimPathOffset(float trimPathOffset) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000167 VD_SET_PROP_WITH_FLAG(mTrimPathOffset, trimPathOffset, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800168 }
169 bool getProperties(int8_t* outProperties, int length);
170
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800171 void setFillGradient(SkShader* fillGradient) {
172 SkRefCnt_SafeAssign(mFillGradient, fillGradient);
173 };
174 void setStrokeGradient(SkShader* strokeGradient) {
175 SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
176 };
177
178
Doris Liu4bbc2932015-12-01 17:59:40 -0800179protected:
180 const SkPath& getUpdatedPath() override;
Doris Liuc2de46f2016-01-21 12:55:54 -0800181 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800182 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800183
184private:
185 // Applies trimming to the specified path.
186 void applyTrim();
Doris Liu5a11e8d2016-02-04 20:04:10 +0000187 float mStrokeWidth = 0;
188 SkColor mStrokeColor = SK_ColorTRANSPARENT;
189 float mStrokeAlpha = 1;
190 SkColor mFillColor = SK_ColorTRANSPARENT;
Doris Liuf276acd2016-01-07 13:49:26 -0800191 SkShader* mStrokeGradient = nullptr;
192 SkShader* mFillGradient = nullptr;
Doris Liu5a11e8d2016-02-04 20:04:10 +0000193 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;
Doris Liu4bbc2932015-12-01 17:59:40 -0800203};
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:
Doris Liuc2de46f2016-01-21 12:55:54 -0800213 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800214 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800215};
216
217class ANDROID_API Group: public Node {
218public:
219 Group(const Group& group);
220 Group() {}
221 float getRotation() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000222 return mRotate;
Doris Liu4bbc2932015-12-01 17:59:40 -0800223 }
224 void setRotation(float rotation) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000225 mRotate = rotation;
Doris Liu4bbc2932015-12-01 17:59:40 -0800226 }
227 float getPivotX() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000228 return mPivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800229 }
230 void setPivotX(float pivotX) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000231 mPivotX = pivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800232 }
233 float getPivotY() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000234 return mPivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800235 }
236 void setPivotY(float pivotY) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000237 mPivotY = pivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800238 }
239 float getScaleX() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000240 return mScaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800241 }
242 void setScaleX(float scaleX) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000243 mScaleX = scaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800244 }
245 float getScaleY() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000246 return mScaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800247 }
248 void setScaleY(float scaleY) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000249 mScaleY = scaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800250 }
251 float getTranslateX() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000252 return mTranslateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800253 }
254 void setTranslateX(float translateX) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000255 mTranslateX = translateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800256 }
257 float getTranslateY() {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000258 return mTranslateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800259 }
260 void setTranslateY(float translateY) {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000261 mTranslateY = translateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800262 }
Doris Liuc2de46f2016-01-21 12:55:54 -0800263 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -0800264 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 {
Doris Liu5a11e8d2016-02-04 20:04:10 +0000274 Rotate_Property = 0,
275 PivotX_Property,
276 PivotY_Property,
277 ScaleX_Property,
278 ScaleY_Property,
279 TranslateX_Property,
280 TranslateY_Property,
Doris Liu4bbc2932015-12-01 17:59:40 -0800281 // Count of the properties, must be at the end.
282 Count,
283 };
Doris Liu5a11e8d2016-02-04 20:04:10 +0000284 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;
Doris Liu4bbc2932015-12-01 17:59:40 -0800291 std::vector<Node*> mChildren;
292};
293
Doris Liu5a11e8d2016-02-04 20:04:10 +0000294class ANDROID_API Tree {
Doris Liu4bbc2932015-12-01 17:59:40 -0800295public:
296 Tree(Group* rootNode) : mRootNode(rootNode) {}
297 void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
298 const SkRect& bounds, bool needsMirroring, bool canReuseCache);
Doris Liu5a11e8d2016-02-04 20:04:10 +0000299 void drawCachedBitmapWithRootAlpha(Canvas* outCanvas, SkColorFilter* filter,
300 const SkRect& originalBounds);
Doris Liu4bbc2932015-12-01 17:59:40 -0800301
Doris Liu5a11e8d2016-02-04 20:04:10 +0000302 void updateCachedBitmap(int width, int height);
Doris Liu4bbc2932015-12-01 17:59:40 -0800303 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 }
Doris Liu4bbc2932015-12-01 17:59:40 -0800319
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