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