VectorDrawable.h revision f276acd98457bcaabc9e79a17a736b3b484f005e
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 22#include <SkBitmap.h> 23#include <SkColor.h> 24#include <SkCanvas.h> 25#include <SkMatrix.h> 26#include <SkPaint.h> 27#include <SkPath.h> 28#include <SkPathMeasure.h> 29#include <SkRect.h> 30#include <SkShader.h> 31 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() {} 62 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, 63 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); 91 void draw(SkCanvas* outCanvas, const SkMatrix& groupStackedMatrix, 92 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(); 99 virtual void drawPath(SkCanvas *outCanvas, const SkPath& renderPath, 100 float strokeScale, const SkMatrix& matrix) = 0; 101 Data mData; 102 SkPath mSkPath; 103 bool mSkPathDirty = true; 104}; 105 106class ANDROID_API FullPath: public Path { 107public: 108 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 123 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 128 ~FullPath() { 129 SkSafeUnref(mFillGradient); 130 SkSafeUnref(mStrokeGradient); 131 } 132 133 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); 137 // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI 138 float getStrokeWidth() { 139 return mProperties.strokeWidth; 140 } 141 void setStrokeWidth(float strokeWidth) { 142 mProperties.strokeWidth = strokeWidth; 143 } 144 SkColor getStrokeColor() { 145 return mProperties.strokeColor; 146 } 147 void setStrokeColor(SkColor strokeColor) { 148 mProperties.strokeColor = strokeColor; 149 } 150 float getStrokeAlpha() { 151 return mProperties.strokeAlpha; 152 } 153 void setStrokeAlpha(float strokeAlpha) { 154 mProperties.strokeAlpha = strokeAlpha; 155 } 156 SkColor getFillColor() { 157 return mProperties.fillColor; 158 } 159 void setFillColor(SkColor fillColor) { 160 mProperties.fillColor = fillColor; 161 } 162 float getFillAlpha() { 163 return mProperties.fillAlpha; 164 } 165 void setFillAlpha(float fillAlpha) { 166 mProperties.fillAlpha = fillAlpha; 167 } 168 float getTrimPathStart() { 169 return mProperties.trimPathStart; 170 } 171 void setTrimPathStart(float trimPathStart) { 172 VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty); 173 } 174 float getTrimPathEnd() { 175 return mProperties.trimPathEnd; 176 } 177 void setTrimPathEnd(float trimPathEnd) { 178 VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty); 179 } 180 float getTrimPathOffset() { 181 return mProperties.trimPathOffset; 182 } 183 void setTrimPathOffset(float trimPathOffset) { 184 VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty); 185 } 186 bool getProperties(int8_t* outProperties, int length); 187 void setColorPropertyValue(int propertyId, int32_t value); 188 void setPropertyValue(int propertyId, float value); 189 190 void setFillGradient(SkShader* fillGradient) { 191 SkRefCnt_SafeAssign(mFillGradient, fillGradient); 192 }; 193 void setStrokeGradient(SkShader* strokeGradient) { 194 SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient); 195 }; 196 197 198protected: 199 const SkPath& getUpdatedPath() override; 200 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, 201 float strokeScale, const SkMatrix& matrix) override; 202 203private: 204 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 }; 218 // Applies trimming to the specified path. 219 void applyTrim(); 220 Properties mProperties; 221 bool mTrimDirty = true; 222 SkPath mTrimmedSkPath; 223 SkPaint mPaint; 224 SkShader* mStrokeGradient = nullptr; 225 SkShader* mFillGradient = nullptr; 226}; 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: 236 void drawPath(SkCanvas* outCanvas, const SkPath& renderPath, 237 float strokeScale, const SkMatrix& matrix) override; 238}; 239 240class ANDROID_API Group: public Node { 241public: 242 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 }; 251 Group(const Group& group); 252 Group() {} 253 float getRotation() { 254 return mProperties.rotate; 255 } 256 void setRotation(float rotation) { 257 mProperties.rotate = rotation; 258 } 259 float getPivotX() { 260 return mProperties.pivotX; 261 } 262 void setPivotX(float pivotX) { 263 mProperties.pivotX = pivotX; 264 } 265 float getPivotY() { 266 return mProperties.pivotY; 267 } 268 void setPivotY(float pivotY) { 269 mProperties.pivotY = pivotY; 270 } 271 float getScaleX() { 272 return mProperties.scaleX; 273 } 274 void setScaleX(float scaleX) { 275 mProperties.scaleX = scaleX; 276 } 277 float getScaleY() { 278 return mProperties.scaleY; 279 } 280 void setScaleY(float scaleY) { 281 mProperties.scaleY = scaleY; 282 } 283 float getTranslateX() { 284 return mProperties.translateX; 285 } 286 void setTranslateX(float translateX) { 287 mProperties.translateX = translateX; 288 } 289 float getTranslateY() { 290 return mProperties.translateY; 291 } 292 void setTranslateY(float translateY) { 293 mProperties.translateY = translateY; 294 } 295 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, 296 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); 303 float getPropertyValue(int propertyId) const; 304 void setPropertyValue(int propertyId, float value); 305 static bool isValidProperty(int propertyId); 306 307private: 308 enum class Property { 309 Rotate = 0, 310 PivotX, 311 PivotY, 312 ScaleX, 313 ScaleY, 314 TranslateX, 315 TranslateY, 316 // Count of the properties, must be at the end. 317 Count, 318 }; 319 std::vector<Node*> mChildren; 320 Properties mProperties; 321}; 322 323class ANDROID_API Tree : public VirtualLightRefBase { 324public: 325 Tree(Group* rootNode) : mRootNode(rootNode) {} 326 void draw(Canvas* outCanvas, SkColorFilter* colorFilter, 327 const SkRect& bounds, bool needsMirroring, bool canReuseCache); 328 329 const SkBitmap& getBitmapUpdateIfDirty(); 330 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 } 346 SkPaint* getPaint(); 347 const SkRect& getBounds() const { 348 return mBounds; 349 } 350 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 363 Group* mRootNode; 364 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 379