blob: 7a45bf5ca8a8322e8d5d3d4cda28fdc3b4cd0b12 [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
sergeyvdccca442016-03-21 15:38:21 -070020#include "hwui/Canvas.h"
Doris Liu766431a2016-02-04 22:17:11 +000021
Doris Liu4bbc2932015-12-01 17:59:40 -080022#include <SkBitmap.h>
23#include <SkColor.h>
Doris Liuc2de46f2016-01-21 12:55:54 -080024#include <SkCanvas.h>
Doris Liu4bbc2932015-12-01 17:59:40 -080025#include <SkMatrix.h>
26#include <SkPaint.h>
27#include <SkPath.h>
28#include <SkPathMeasure.h>
29#include <SkRect.h>
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -080030#include <SkShader.h>
Doris Liu4bbc2932015-12-01 17:59:40 -080031
32#include <cutils/compiler.h>
33#include <stddef.h>
34#include <vector>
35#include <string>
36
37namespace android {
38namespace uirenderer {
39
40namespace VectorDrawable {
41#define VD_SET_PROP_WITH_FLAG(field, value, flag) (VD_SET_PROP(field, value) ? (flag = true, true): false);
42#define VD_SET_PROP(field, value) (value != field ? (field = value, true) : false)
43
44/* A VectorDrawable is composed of a tree of nodes.
45 * Each node can be a group node, or a path.
46 * A group node can have groups or paths as children, but a path node has
47 * no children.
48 * One example can be:
49 * Root Group
50 * / | \
51 * Group Path Group
52 * / \ |
53 * Path Path Path
54 *
55 */
56class ANDROID_API Node {
57public:
58 Node(const Node& node) {
59 mName = node.mName;
60 }
61 Node() {}
Doris Liuc2de46f2016-01-21 12:55:54 -080062 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080063 float scaleX, float scaleY) = 0;
64 virtual void dump() = 0;
65 void setName(const char* name) {
66 mName = name;
67 }
68 virtual ~Node(){}
69protected:
70 std::string mName;
71};
72
73class ANDROID_API Path : public Node {
74public:
75 struct ANDROID_API Data {
76 std::vector<char> verbs;
77 std::vector<size_t> verbSizes;
78 std::vector<float> points;
79 bool operator==(const Data& data) const {
80 return verbs == data.verbs && verbSizes == data.verbSizes
81 && points == data.points;
82 }
83 };
84 Path(const Data& nodes);
85 Path(const Path& path);
86 Path(const char* path, size_t strLength);
87 Path() {}
88 void dump() override;
89 bool canMorph(const Data& path);
90 bool canMorph(const Path& path);
Doris Liuc2de46f2016-01-21 12:55:54 -080091 void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -080092 float scaleX, float scaleY) override;
93 void setPath(const char* path, size_t strLength);
94 void setPathData(const Data& data);
95 static float getMatrixScale(const SkMatrix& groupStackedMatrix);
96
97protected:
98 virtual const SkPath& getUpdatedPath();
Teng-Hui Zhu46591f42016-03-15 14:32:16 -070099 virtual void drawPath(SkCanvas *outCanvas, SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800100 float strokeScale, const SkMatrix& matrix) = 0;
Doris Liu4bbc2932015-12-01 17:59:40 -0800101 Data mData;
102 SkPath mSkPath;
103 bool mSkPathDirty = true;
104};
105
106class ANDROID_API FullPath: public Path {
107public:
Doris Liu766431a2016-02-04 22:17:11 +0000108
109struct Properties {
110 float strokeWidth = 0;
111 SkColor strokeColor = SK_ColorTRANSPARENT;
112 float strokeAlpha = 1;
113 SkColor fillColor = SK_ColorTRANSPARENT;
114 float fillAlpha = 1;
115 float trimPathStart = 0;
116 float trimPathEnd = 1;
117 float trimPathOffset = 0;
118 int32_t strokeLineCap = SkPaint::Cap::kButt_Cap;
119 int32_t strokeLineJoin = SkPaint::Join::kMiter_Join;
120 float strokeMiterLimit = 4;
Teng-Hui Zhu46591f42016-03-15 14:32:16 -0700121 int fillType = 0; /* non-zero or kWinding_FillType in Skia */
Doris Liu766431a2016-02-04 22:17:11 +0000122};
123
Doris Liu4bbc2932015-12-01 17:59:40 -0800124 FullPath(const FullPath& path); // for cloning
125 FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
126 FullPath() : Path() {}
127 FullPath(const Data& nodes) : Path(nodes) {}
128
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800129 ~FullPath() {
130 SkSafeUnref(mFillGradient);
131 SkSafeUnref(mStrokeGradient);
132 }
133
Doris Liu4bbc2932015-12-01 17:59:40 -0800134 void updateProperties(float strokeWidth, SkColor strokeColor,
135 float strokeAlpha, SkColor fillColor, float fillAlpha,
136 float trimPathStart, float trimPathEnd, float trimPathOffset,
Teng-Hui Zhu46591f42016-03-15 14:32:16 -0700137 float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType);
Doris Liu766431a2016-02-04 22:17:11 +0000138 // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
Doris Liu4bbc2932015-12-01 17:59:40 -0800139 float getStrokeWidth() {
Doris Liu766431a2016-02-04 22:17:11 +0000140 return mProperties.strokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800141 }
142 void setStrokeWidth(float strokeWidth) {
Doris Liu766431a2016-02-04 22:17:11 +0000143 mProperties.strokeWidth = strokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800144 }
145 SkColor getStrokeColor() {
Doris Liu766431a2016-02-04 22:17:11 +0000146 return mProperties.strokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800147 }
148 void setStrokeColor(SkColor strokeColor) {
Doris Liu766431a2016-02-04 22:17:11 +0000149 mProperties.strokeColor = strokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800150 }
151 float getStrokeAlpha() {
Doris Liu766431a2016-02-04 22:17:11 +0000152 return mProperties.strokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800153 }
154 void setStrokeAlpha(float strokeAlpha) {
Doris Liu766431a2016-02-04 22:17:11 +0000155 mProperties.strokeAlpha = strokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800156 }
157 SkColor getFillColor() {
Doris Liu766431a2016-02-04 22:17:11 +0000158 return mProperties.fillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800159 }
160 void setFillColor(SkColor fillColor) {
Doris Liu766431a2016-02-04 22:17:11 +0000161 mProperties.fillColor = fillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800162 }
163 float getFillAlpha() {
Doris Liu766431a2016-02-04 22:17:11 +0000164 return mProperties.fillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800165 }
166 void setFillAlpha(float fillAlpha) {
Doris Liu766431a2016-02-04 22:17:11 +0000167 mProperties.fillAlpha = fillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800168 }
169 float getTrimPathStart() {
Doris Liu766431a2016-02-04 22:17:11 +0000170 return mProperties.trimPathStart;
Doris Liu4bbc2932015-12-01 17:59:40 -0800171 }
172 void setTrimPathStart(float trimPathStart) {
Doris Liu766431a2016-02-04 22:17:11 +0000173 VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800174 }
175 float getTrimPathEnd() {
Doris Liu766431a2016-02-04 22:17:11 +0000176 return mProperties.trimPathEnd;
Doris Liu4bbc2932015-12-01 17:59:40 -0800177 }
178 void setTrimPathEnd(float trimPathEnd) {
Doris Liu766431a2016-02-04 22:17:11 +0000179 VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800180 }
181 float getTrimPathOffset() {
Doris Liu766431a2016-02-04 22:17:11 +0000182 return mProperties.trimPathOffset;
Doris Liu4bbc2932015-12-01 17:59:40 -0800183 }
184 void setTrimPathOffset(float trimPathOffset) {
Doris Liu766431a2016-02-04 22:17:11 +0000185 VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800186 }
187 bool getProperties(int8_t* outProperties, int length);
Doris Liu766431a2016-02-04 22:17:11 +0000188 void setColorPropertyValue(int propertyId, int32_t value);
189 void setPropertyValue(int propertyId, float value);
Doris Liu4bbc2932015-12-01 17:59:40 -0800190
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800191 void setFillGradient(SkShader* fillGradient) {
192 SkRefCnt_SafeAssign(mFillGradient, fillGradient);
193 };
194 void setStrokeGradient(SkShader* strokeGradient) {
195 SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
196 };
197
198
Doris Liu4bbc2932015-12-01 17:59:40 -0800199protected:
200 const SkPath& getUpdatedPath() override;
Teng-Hui Zhu46591f42016-03-15 14:32:16 -0700201 void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800202 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800203
204private:
Doris Liu766431a2016-02-04 22:17:11 +0000205 enum class Property {
206 StrokeWidth = 0,
207 StrokeColor,
208 StrokeAlpha,
209 FillColor,
210 FillAlpha,
211 TrimPathStart,
212 TrimPathEnd,
213 TrimPathOffset,
214 StrokeLineCap,
215 StrokeLineJoin,
216 StrokeMiterLimit,
Teng-Hui Zhu46591f42016-03-15 14:32:16 -0700217 FillType,
Doris Liu766431a2016-02-04 22:17:11 +0000218 Count,
219 };
Doris Liu4bbc2932015-12-01 17:59:40 -0800220 // Applies trimming to the specified path.
221 void applyTrim();
Doris Liu766431a2016-02-04 22:17:11 +0000222 Properties mProperties;
Doris Liu5a11e8d2016-02-04 20:04:10 +0000223 bool mTrimDirty = true;
Doris Liu5a11e8d2016-02-04 20:04:10 +0000224 SkPath mTrimmedSkPath;
225 SkPaint mPaint;
Doris Liu766431a2016-02-04 22:17:11 +0000226 SkShader* mStrokeGradient = nullptr;
227 SkShader* mFillGradient = nullptr;
Doris Liu4bbc2932015-12-01 17:59:40 -0800228};
229
230class ANDROID_API ClipPath: public Path {
231public:
232 ClipPath(const ClipPath& path) : Path(path) {}
233 ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
234 ClipPath() : Path() {}
235 ClipPath(const Data& nodes) : Path(nodes) {}
236
237protected:
Teng-Hui Zhu46591f42016-03-15 14:32:16 -0700238 void drawPath(SkCanvas* outCanvas, SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800239 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800240};
241
242class ANDROID_API Group: public Node {
243public:
Doris Liu766431a2016-02-04 22:17:11 +0000244 struct Properties {
245 float rotate = 0;
246 float pivotX = 0;
247 float pivotY = 0;
248 float scaleX = 1;
249 float scaleY = 1;
250 float translateX = 0;
251 float translateY = 0;
252 };
Doris Liu4bbc2932015-12-01 17:59:40 -0800253 Group(const Group& group);
254 Group() {}
255 float getRotation() {
Doris Liu766431a2016-02-04 22:17:11 +0000256 return mProperties.rotate;
Doris Liu4bbc2932015-12-01 17:59:40 -0800257 }
258 void setRotation(float rotation) {
Doris Liu766431a2016-02-04 22:17:11 +0000259 mProperties.rotate = rotation;
Doris Liu4bbc2932015-12-01 17:59:40 -0800260 }
261 float getPivotX() {
Doris Liu766431a2016-02-04 22:17:11 +0000262 return mProperties.pivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800263 }
264 void setPivotX(float pivotX) {
Doris Liu766431a2016-02-04 22:17:11 +0000265 mProperties.pivotX = pivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800266 }
267 float getPivotY() {
Doris Liu766431a2016-02-04 22:17:11 +0000268 return mProperties.pivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800269 }
270 void setPivotY(float pivotY) {
Doris Liu766431a2016-02-04 22:17:11 +0000271 mProperties.pivotY = pivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800272 }
273 float getScaleX() {
Doris Liu766431a2016-02-04 22:17:11 +0000274 return mProperties.scaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800275 }
276 void setScaleX(float scaleX) {
Doris Liu766431a2016-02-04 22:17:11 +0000277 mProperties.scaleX = scaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800278 }
279 float getScaleY() {
Doris Liu766431a2016-02-04 22:17:11 +0000280 return mProperties.scaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800281 }
282 void setScaleY(float scaleY) {
Doris Liu766431a2016-02-04 22:17:11 +0000283 mProperties.scaleY = scaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800284 }
285 float getTranslateX() {
Doris Liu766431a2016-02-04 22:17:11 +0000286 return mProperties.translateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800287 }
288 void setTranslateX(float translateX) {
Doris Liu766431a2016-02-04 22:17:11 +0000289 mProperties.translateX = translateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800290 }
291 float getTranslateY() {
Doris Liu766431a2016-02-04 22:17:11 +0000292 return mProperties.translateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800293 }
294 void setTranslateY(float translateY) {
Doris Liu766431a2016-02-04 22:17:11 +0000295 mProperties.translateY = translateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800296 }
Doris Liuc2de46f2016-01-21 12:55:54 -0800297 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -0800298 float scaleX, float scaleY) override;
299 void updateLocalMatrix(float rotate, float pivotX, float pivotY,
300 float scaleX, float scaleY, float translateX, float translateY);
301 void getLocalMatrix(SkMatrix* outMatrix);
302 void addChild(Node* child);
303 void dump() override;
304 bool getProperties(float* outProperties, int length);
Doris Liu766431a2016-02-04 22:17:11 +0000305 float getPropertyValue(int propertyId) const;
306 void setPropertyValue(int propertyId, float value);
307 static bool isValidProperty(int propertyId);
Doris Liu4bbc2932015-12-01 17:59:40 -0800308
309private:
310 enum class Property {
Doris Liu766431a2016-02-04 22:17:11 +0000311 Rotate = 0,
312 PivotX,
313 PivotY,
314 ScaleX,
315 ScaleY,
316 TranslateX,
317 TranslateY,
Doris Liu4bbc2932015-12-01 17:59:40 -0800318 // Count of the properties, must be at the end.
319 Count,
320 };
Doris Liuef062eb2016-02-04 16:16:27 -0800321 std::vector< std::unique_ptr<Node> > mChildren;
Doris Liu766431a2016-02-04 22:17:11 +0000322 Properties mProperties;
Doris Liu4bbc2932015-12-01 17:59:40 -0800323};
324
Doris Liu766431a2016-02-04 22:17:11 +0000325class ANDROID_API Tree : public VirtualLightRefBase {
Doris Liu4bbc2932015-12-01 17:59:40 -0800326public:
327 Tree(Group* rootNode) : mRootNode(rootNode) {}
328 void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
329 const SkRect& bounds, bool needsMirroring, bool canReuseCache);
Doris Liu4bbc2932015-12-01 17:59:40 -0800330
Doris Liu766431a2016-02-04 22:17:11 +0000331 const SkBitmap& getBitmapUpdateIfDirty();
Doris Liu4bbc2932015-12-01 17:59:40 -0800332 void createCachedBitmapIfNeeded(int width, int height);
333 bool canReuseBitmap(int width, int height);
334 void setAllowCaching(bool allowCaching) {
335 mAllowCaching = allowCaching;
336 }
337 bool setRootAlpha(float rootAlpha) {
338 return VD_SET_PROP(mRootAlpha, rootAlpha);
339 }
340
341 float getRootAlpha() {
342 return mRootAlpha;
343 }
344 void setViewportSize(float viewportWidth, float viewportHeight) {
345 mViewportWidth = viewportWidth;
346 mViewportHeight = viewportHeight;
347 }
Doris Liu766431a2016-02-04 22:17:11 +0000348 SkPaint* getPaint();
349 const SkRect& getBounds() const {
350 return mBounds;
351 }
Doris Liu4bbc2932015-12-01 17:59:40 -0800352
353private:
354 // Cap the bitmap size, such that it won't hurt the performance too much
355 // and it won't crash due to a very large scale.
356 // The drawable will look blurry above this size.
357 const static int MAX_CACHED_BITMAP_SIZE;
358
359 bool mCacheDirty = true;
360 bool mAllowCaching = true;
361 float mViewportWidth = 0;
362 float mViewportHeight = 0;
363 float mRootAlpha = 1.0f;
364
Doris Liuef062eb2016-02-04 16:16:27 -0800365 std::unique_ptr<Group> mRootNode;
Doris Liu4bbc2932015-12-01 17:59:40 -0800366 SkRect mBounds;
367 SkMatrix mCanvasMatrix;
368 SkPaint mPaint;
369 SkPathMeasure mPathMeasure;
370 SkBitmap mCachedBitmap;
371
372};
373
374} // namespace VectorDrawable
375
376typedef VectorDrawable::Path::Data PathData;
377} // namespace uirenderer
378} // namespace android
379
380#endif // ANDROID_HWUI_VPATH_H