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