blob: 5ae5f6a3bdba103fa43f6929367efec091600f17 [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>
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() {}
Doris Liuc2de46f2016-01-21 12:55:54 -080060 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080061 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);
Doris Liuc2de46f2016-01-21 12:55:54 -080089 void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080090 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();
Doris Liuc2de46f2016-01-21 12:55:54 -080097 virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath,
Doris Liu4bbc2932015-12-01 17:59:40 -080098 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;
Doris Liuc2de46f2016-01-21 12:55:54 -0800167 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Doris Liu4bbc2932015-12-01 17:59:40 -0800168 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:
Doris Liuc2de46f2016-01-21 12:55:54 -0800197 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Doris Liu4bbc2932015-12-01 17:59:40 -0800198 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 }
Doris Liuc2de46f2016-01-21 12:55:54 -0800247 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -0800248 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