blob: 36a8aebeaa332c77ee4b3e6e659b8bb9aee0197e [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"
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();
Doris Liuc2de46f2016-01-21 12:55:54 -080099 virtual void drawPath(SkCanvas *outCanvas, const 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;
121};
122
Doris Liu4bbc2932015-12-01 17:59:40 -0800123 FullPath(const FullPath& path); // for cloning
124 FullPath(const char* path, size_t strLength) : Path(path, strLength) {}
125 FullPath() : Path() {}
126 FullPath(const Data& nodes) : Path(nodes) {}
127
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800128 ~FullPath() {
129 SkSafeUnref(mFillGradient);
130 SkSafeUnref(mStrokeGradient);
131 }
132
Doris Liu4bbc2932015-12-01 17:59:40 -0800133 void updateProperties(float strokeWidth, SkColor strokeColor,
134 float strokeAlpha, SkColor fillColor, float fillAlpha,
135 float trimPathStart, float trimPathEnd, float trimPathOffset,
136 float strokeMiterLimit, int strokeLineCap, int strokeLineJoin);
Doris Liu766431a2016-02-04 22:17:11 +0000137 // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI
Doris Liu4bbc2932015-12-01 17:59:40 -0800138 float getStrokeWidth() {
Doris Liu766431a2016-02-04 22:17:11 +0000139 return mProperties.strokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800140 }
141 void setStrokeWidth(float strokeWidth) {
Doris Liu766431a2016-02-04 22:17:11 +0000142 mProperties.strokeWidth = strokeWidth;
Doris Liu4bbc2932015-12-01 17:59:40 -0800143 }
144 SkColor getStrokeColor() {
Doris Liu766431a2016-02-04 22:17:11 +0000145 return mProperties.strokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800146 }
147 void setStrokeColor(SkColor strokeColor) {
Doris Liu766431a2016-02-04 22:17:11 +0000148 mProperties.strokeColor = strokeColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800149 }
150 float getStrokeAlpha() {
Doris Liu766431a2016-02-04 22:17:11 +0000151 return mProperties.strokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800152 }
153 void setStrokeAlpha(float strokeAlpha) {
Doris Liu766431a2016-02-04 22:17:11 +0000154 mProperties.strokeAlpha = strokeAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800155 }
156 SkColor getFillColor() {
Doris Liu766431a2016-02-04 22:17:11 +0000157 return mProperties.fillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800158 }
159 void setFillColor(SkColor fillColor) {
Doris Liu766431a2016-02-04 22:17:11 +0000160 mProperties.fillColor = fillColor;
Doris Liu4bbc2932015-12-01 17:59:40 -0800161 }
162 float getFillAlpha() {
Doris Liu766431a2016-02-04 22:17:11 +0000163 return mProperties.fillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800164 }
165 void setFillAlpha(float fillAlpha) {
Doris Liu766431a2016-02-04 22:17:11 +0000166 mProperties.fillAlpha = fillAlpha;
Doris Liu4bbc2932015-12-01 17:59:40 -0800167 }
168 float getTrimPathStart() {
Doris Liu766431a2016-02-04 22:17:11 +0000169 return mProperties.trimPathStart;
Doris Liu4bbc2932015-12-01 17:59:40 -0800170 }
171 void setTrimPathStart(float trimPathStart) {
Doris Liu766431a2016-02-04 22:17:11 +0000172 VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800173 }
174 float getTrimPathEnd() {
Doris Liu766431a2016-02-04 22:17:11 +0000175 return mProperties.trimPathEnd;
Doris Liu4bbc2932015-12-01 17:59:40 -0800176 }
177 void setTrimPathEnd(float trimPathEnd) {
Doris Liu766431a2016-02-04 22:17:11 +0000178 VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800179 }
180 float getTrimPathOffset() {
Doris Liu766431a2016-02-04 22:17:11 +0000181 return mProperties.trimPathOffset;
Doris Liu4bbc2932015-12-01 17:59:40 -0800182 }
183 void setTrimPathOffset(float trimPathOffset) {
Doris Liu766431a2016-02-04 22:17:11 +0000184 VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty);
Doris Liu4bbc2932015-12-01 17:59:40 -0800185 }
186 bool getProperties(int8_t* outProperties, int length);
Doris Liu766431a2016-02-04 22:17:11 +0000187 void setColorPropertyValue(int propertyId, int32_t value);
188 void setPropertyValue(int propertyId, float value);
Doris Liu4bbc2932015-12-01 17:59:40 -0800189
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800190 void setFillGradient(SkShader* fillGradient) {
191 SkRefCnt_SafeAssign(mFillGradient, fillGradient);
192 };
193 void setStrokeGradient(SkShader* strokeGradient) {
194 SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient);
195 };
196
197
Doris Liu4bbc2932015-12-01 17:59:40 -0800198protected:
199 const SkPath& getUpdatedPath() override;
Doris Liuc2de46f2016-01-21 12:55:54 -0800200 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800201 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800202
203private:
Doris Liu766431a2016-02-04 22:17:11 +0000204 enum class Property {
205 StrokeWidth = 0,
206 StrokeColor,
207 StrokeAlpha,
208 FillColor,
209 FillAlpha,
210 TrimPathStart,
211 TrimPathEnd,
212 TrimPathOffset,
213 StrokeLineCap,
214 StrokeLineJoin,
215 StrokeMiterLimit,
216 Count,
217 };
Doris Liu4bbc2932015-12-01 17:59:40 -0800218 // Applies trimming to the specified path.
219 void applyTrim();
Doris Liu766431a2016-02-04 22:17:11 +0000220 Properties mProperties;
Doris Liu5a11e8d2016-02-04 20:04:10 +0000221 bool mTrimDirty = true;
Doris Liu5a11e8d2016-02-04 20:04:10 +0000222 SkPath mTrimmedSkPath;
223 SkPaint mPaint;
Doris Liu766431a2016-02-04 22:17:11 +0000224 SkShader* mStrokeGradient = nullptr;
225 SkShader* mFillGradient = nullptr;
Doris Liu4bbc2932015-12-01 17:59:40 -0800226};
227
228class ANDROID_API ClipPath: public Path {
229public:
230 ClipPath(const ClipPath& path) : Path(path) {}
231 ClipPath(const char* path, size_t strLength) : Path(path, strLength) {}
232 ClipPath() : Path() {}
233 ClipPath(const Data& nodes) : Path(nodes) {}
234
235protected:
Doris Liuc2de46f2016-01-21 12:55:54 -0800236 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath,
Teng-Hui Zhudbee9bb2015-12-15 11:01:27 -0800237 float strokeScale, const SkMatrix& matrix) override;
Doris Liu4bbc2932015-12-01 17:59:40 -0800238};
239
240class ANDROID_API Group: public Node {
241public:
Doris Liu766431a2016-02-04 22:17:11 +0000242 struct Properties {
243 float rotate = 0;
244 float pivotX = 0;
245 float pivotY = 0;
246 float scaleX = 1;
247 float scaleY = 1;
248 float translateX = 0;
249 float translateY = 0;
250 };
Doris Liu4bbc2932015-12-01 17:59:40 -0800251 Group(const Group& group);
252 Group() {}
253 float getRotation() {
Doris Liu766431a2016-02-04 22:17:11 +0000254 return mProperties.rotate;
Doris Liu4bbc2932015-12-01 17:59:40 -0800255 }
256 void setRotation(float rotation) {
Doris Liu766431a2016-02-04 22:17:11 +0000257 mProperties.rotate = rotation;
Doris Liu4bbc2932015-12-01 17:59:40 -0800258 }
259 float getPivotX() {
Doris Liu766431a2016-02-04 22:17:11 +0000260 return mProperties.pivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800261 }
262 void setPivotX(float pivotX) {
Doris Liu766431a2016-02-04 22:17:11 +0000263 mProperties.pivotX = pivotX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800264 }
265 float getPivotY() {
Doris Liu766431a2016-02-04 22:17:11 +0000266 return mProperties.pivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800267 }
268 void setPivotY(float pivotY) {
Doris Liu766431a2016-02-04 22:17:11 +0000269 mProperties.pivotY = pivotY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800270 }
271 float getScaleX() {
Doris Liu766431a2016-02-04 22:17:11 +0000272 return mProperties.scaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800273 }
274 void setScaleX(float scaleX) {
Doris Liu766431a2016-02-04 22:17:11 +0000275 mProperties.scaleX = scaleX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800276 }
277 float getScaleY() {
Doris Liu766431a2016-02-04 22:17:11 +0000278 return mProperties.scaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800279 }
280 void setScaleY(float scaleY) {
Doris Liu766431a2016-02-04 22:17:11 +0000281 mProperties.scaleY = scaleY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800282 }
283 float getTranslateX() {
Doris Liu766431a2016-02-04 22:17:11 +0000284 return mProperties.translateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800285 }
286 void setTranslateX(float translateX) {
Doris Liu766431a2016-02-04 22:17:11 +0000287 mProperties.translateX = translateX;
Doris Liu4bbc2932015-12-01 17:59:40 -0800288 }
289 float getTranslateY() {
Doris Liu766431a2016-02-04 22:17:11 +0000290 return mProperties.translateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800291 }
292 void setTranslateY(float translateY) {
Doris Liu766431a2016-02-04 22:17:11 +0000293 mProperties.translateY = translateY;
Doris Liu4bbc2932015-12-01 17:59:40 -0800294 }
Doris Liuc2de46f2016-01-21 12:55:54 -0800295 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix,
Doris Liu4bbc2932015-12-01 17:59:40 -0800296 float scaleX, float scaleY) override;
297 void updateLocalMatrix(float rotate, float pivotX, float pivotY,
298 float scaleX, float scaleY, float translateX, float translateY);
299 void getLocalMatrix(SkMatrix* outMatrix);
300 void addChild(Node* child);
301 void dump() override;
302 bool getProperties(float* outProperties, int length);
Doris Liu766431a2016-02-04 22:17:11 +0000303 float getPropertyValue(int propertyId) const;
304 void setPropertyValue(int propertyId, float value);
305 static bool isValidProperty(int propertyId);
Doris Liu4bbc2932015-12-01 17:59:40 -0800306
307private:
308 enum class Property {
Doris Liu766431a2016-02-04 22:17:11 +0000309 Rotate = 0,
310 PivotX,
311 PivotY,
312 ScaleX,
313 ScaleY,
314 TranslateX,
315 TranslateY,
Doris Liu4bbc2932015-12-01 17:59:40 -0800316 // Count of the properties, must be at the end.
317 Count,
318 };
Doris Liuef062eb2016-02-04 16:16:27 -0800319 std::vector< std::unique_ptr<Node> > mChildren;
Doris Liu766431a2016-02-04 22:17:11 +0000320 Properties mProperties;
Doris Liu4bbc2932015-12-01 17:59:40 -0800321};
322
Doris Liu766431a2016-02-04 22:17:11 +0000323class ANDROID_API Tree : public VirtualLightRefBase {
Doris Liu4bbc2932015-12-01 17:59:40 -0800324public:
325 Tree(Group* rootNode) : mRootNode(rootNode) {}
326 void draw(Canvas* outCanvas, SkColorFilter* colorFilter,
327 const SkRect& bounds, bool needsMirroring, bool canReuseCache);
Doris Liu4bbc2932015-12-01 17:59:40 -0800328
Doris Liu766431a2016-02-04 22:17:11 +0000329 const SkBitmap& getBitmapUpdateIfDirty();
Doris Liu4bbc2932015-12-01 17:59:40 -0800330 void createCachedBitmapIfNeeded(int width, int height);
331 bool canReuseBitmap(int width, int height);
332 void setAllowCaching(bool allowCaching) {
333 mAllowCaching = allowCaching;
334 }
335 bool setRootAlpha(float rootAlpha) {
336 return VD_SET_PROP(mRootAlpha, rootAlpha);
337 }
338
339 float getRootAlpha() {
340 return mRootAlpha;
341 }
342 void setViewportSize(float viewportWidth, float viewportHeight) {
343 mViewportWidth = viewportWidth;
344 mViewportHeight = viewportHeight;
345 }
Doris Liu766431a2016-02-04 22:17:11 +0000346 SkPaint* getPaint();
347 const SkRect& getBounds() const {
348 return mBounds;
349 }
Doris Liu4bbc2932015-12-01 17:59:40 -0800350
351private:
352 // Cap the bitmap size, such that it won't hurt the performance too much
353 // and it won't crash due to a very large scale.
354 // The drawable will look blurry above this size.
355 const static int MAX_CACHED_BITMAP_SIZE;
356
357 bool mCacheDirty = true;
358 bool mAllowCaching = true;
359 float mViewportWidth = 0;
360 float mViewportHeight = 0;
361 float mRootAlpha = 1.0f;
362
Doris Liuef062eb2016-02-04 16:16:27 -0800363 std::unique_ptr<Group> mRootNode;
Doris Liu4bbc2932015-12-01 17:59:40 -0800364 SkRect mBounds;
365 SkMatrix mCanvasMatrix;
366 SkPaint mPaint;
367 SkPathMeasure mPathMeasure;
368 SkBitmap mCachedBitmap;
369
370};
371
372} // namespace VectorDrawable
373
374typedef VectorDrawable::Path::Data PathData;
375} // namespace uirenderer
376} // namespace android
377
378#endif // ANDROID_HWUI_VPATH_H