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