VectorDrawable.h revision 4bbc2931263b232fba61807fca00e127573eff42
1/* 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 331