VectorDrawable.h revision a7f6bba1a3565c19715e878dfe7f0e01022944ff
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 "hwui/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, 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 int fillType = 0; /* non-zero or kWinding_FillType in Skia */ 122}; 123 124 FullPath(const FullPath& path); // for cloning 125 FullPath(const char* path, size_t strLength) : Path(path, strLength) {} 126 FullPath() : Path() {} 127 FullPath(const Data& nodes) : Path(nodes) {} 128 129 ~FullPath() { 130 SkSafeUnref(mFillGradient); 131 SkSafeUnref(mStrokeGradient); 132 } 133 134 void updateProperties(float strokeWidth, SkColor strokeColor, 135 float strokeAlpha, SkColor fillColor, float fillAlpha, 136 float trimPathStart, float trimPathEnd, float trimPathOffset, 137 float strokeMiterLimit, int strokeLineCap, int strokeLineJoin, int fillType); 138 // TODO: Cleanup: Remove the setter and getters below, and their counterparts in java and JNI 139 float getStrokeWidth() { 140 return mProperties.strokeWidth; 141 } 142 void setStrokeWidth(float strokeWidth) { 143 mProperties.strokeWidth = strokeWidth; 144 } 145 SkColor getStrokeColor() { 146 return mProperties.strokeColor; 147 } 148 void setStrokeColor(SkColor strokeColor) { 149 mProperties.strokeColor = strokeColor; 150 } 151 float getStrokeAlpha() { 152 return mProperties.strokeAlpha; 153 } 154 void setStrokeAlpha(float strokeAlpha) { 155 mProperties.strokeAlpha = strokeAlpha; 156 } 157 SkColor getFillColor() { 158 return mProperties.fillColor; 159 } 160 void setFillColor(SkColor fillColor) { 161 mProperties.fillColor = fillColor; 162 } 163 float getFillAlpha() { 164 return mProperties.fillAlpha; 165 } 166 void setFillAlpha(float fillAlpha) { 167 mProperties.fillAlpha = fillAlpha; 168 } 169 float getTrimPathStart() { 170 return mProperties.trimPathStart; 171 } 172 void setTrimPathStart(float trimPathStart) { 173 VD_SET_PROP_WITH_FLAG(mProperties.trimPathStart, trimPathStart, mTrimDirty); 174 } 175 float getTrimPathEnd() { 176 return mProperties.trimPathEnd; 177 } 178 void setTrimPathEnd(float trimPathEnd) { 179 VD_SET_PROP_WITH_FLAG(mProperties.trimPathEnd, trimPathEnd, mTrimDirty); 180 } 181 float getTrimPathOffset() { 182 return mProperties.trimPathOffset; 183 } 184 void setTrimPathOffset(float trimPathOffset) { 185 VD_SET_PROP_WITH_FLAG(mProperties.trimPathOffset, trimPathOffset, mTrimDirty); 186 } 187 bool getProperties(int8_t* outProperties, int length); 188 void setColorPropertyValue(int propertyId, int32_t value); 189 void setPropertyValue(int propertyId, float value); 190 191 void setFillGradient(SkShader* fillGradient) { 192 SkRefCnt_SafeAssign(mFillGradient, fillGradient); 193 }; 194 void setStrokeGradient(SkShader* strokeGradient) { 195 SkRefCnt_SafeAssign(mStrokeGradient, strokeGradient); 196 }; 197 198 199protected: 200 const SkPath& getUpdatedPath() override; 201 void drawPath(SkCanvas* outCanvas, SkPath& renderPath, 202 float strokeScale, const SkMatrix& matrix) override; 203 204private: 205 enum class Property { 206 StrokeWidth = 0, 207 StrokeColor, 208 StrokeAlpha, 209 FillColor, 210 FillAlpha, 211 TrimPathStart, 212 TrimPathEnd, 213 TrimPathOffset, 214 StrokeLineCap, 215 StrokeLineJoin, 216 StrokeMiterLimit, 217 FillType, 218 Count, 219 }; 220 // Applies trimming to the specified path. 221 void applyTrim(); 222 Properties mProperties; 223 bool mTrimDirty = true; 224 SkPath mTrimmedSkPath; 225 SkPaint mPaint; 226 SkShader* mStrokeGradient = nullptr; 227 SkShader* mFillGradient = nullptr; 228}; 229 230class ANDROID_API ClipPath: public Path { 231public: 232 ClipPath(const ClipPath& path) : Path(path) {} 233 ClipPath(const char* path, size_t strLength) : Path(path, strLength) {} 234 ClipPath() : Path() {} 235 ClipPath(const Data& nodes) : Path(nodes) {} 236 237protected: 238 void drawPath(SkCanvas* outCanvas, SkPath& renderPath, 239 float strokeScale, const SkMatrix& matrix) override; 240}; 241 242class ANDROID_API Group: public Node { 243public: 244 struct Properties { 245 float rotate = 0; 246 float pivotX = 0; 247 float pivotY = 0; 248 float scaleX = 1; 249 float scaleY = 1; 250 float translateX = 0; 251 float translateY = 0; 252 }; 253 Group(const Group& group); 254 Group() {} 255 float getRotation() { 256 return mProperties.rotate; 257 } 258 void setRotation(float rotation) { 259 mProperties.rotate = rotation; 260 } 261 float getPivotX() { 262 return mProperties.pivotX; 263 } 264 void setPivotX(float pivotX) { 265 mProperties.pivotX = pivotX; 266 } 267 float getPivotY() { 268 return mProperties.pivotY; 269 } 270 void setPivotY(float pivotY) { 271 mProperties.pivotY = pivotY; 272 } 273 float getScaleX() { 274 return mProperties.scaleX; 275 } 276 void setScaleX(float scaleX) { 277 mProperties.scaleX = scaleX; 278 } 279 float getScaleY() { 280 return mProperties.scaleY; 281 } 282 void setScaleY(float scaleY) { 283 mProperties.scaleY = scaleY; 284 } 285 float getTranslateX() { 286 return mProperties.translateX; 287 } 288 void setTranslateX(float translateX) { 289 mProperties.translateX = translateX; 290 } 291 float getTranslateY() { 292 return mProperties.translateY; 293 } 294 void setTranslateY(float translateY) { 295 mProperties.translateY = translateY; 296 } 297 virtual void draw(SkCanvas* outCanvas, const SkMatrix& currentMatrix, 298 float scaleX, float scaleY) override; 299 void updateLocalMatrix(float rotate, float pivotX, float pivotY, 300 float scaleX, float scaleY, float translateX, float translateY); 301 void getLocalMatrix(SkMatrix* outMatrix); 302 void addChild(Node* child); 303 void dump() override; 304 bool getProperties(float* outProperties, int length); 305 float getPropertyValue(int propertyId) const; 306 void setPropertyValue(int propertyId, float value); 307 static bool isValidProperty(int propertyId); 308 309private: 310 enum class Property { 311 Rotate = 0, 312 PivotX, 313 PivotY, 314 ScaleX, 315 ScaleY, 316 TranslateX, 317 TranslateY, 318 // Count of the properties, must be at the end. 319 Count, 320 }; 321 std::vector< std::unique_ptr<Node> > mChildren; 322 Properties mProperties; 323}; 324 325class ANDROID_API Tree : public VirtualLightRefBase { 326public: 327 Tree(Group* rootNode) : mRootNode(rootNode) {} 328 void draw(Canvas* outCanvas, SkColorFilter* colorFilter, 329 const SkRect& bounds, bool needsMirroring, bool canReuseCache); 330 331 const SkBitmap& getBitmapUpdateIfDirty(); 332 void createCachedBitmapIfNeeded(int width, int height); 333 bool canReuseBitmap(int width, int height); 334 void setAllowCaching(bool allowCaching) { 335 mAllowCaching = allowCaching; 336 } 337 bool setRootAlpha(float rootAlpha) { 338 return VD_SET_PROP(mRootAlpha, rootAlpha); 339 } 340 341 float getRootAlpha() { 342 return mRootAlpha; 343 } 344 void setViewportSize(float viewportWidth, float viewportHeight) { 345 mViewportWidth = viewportWidth; 346 mViewportHeight = viewportHeight; 347 } 348 SkPaint* getPaint(); 349 const SkRect& getBounds() const { 350 return mBounds; 351 } 352 353private: 354 // Cap the bitmap size, such that it won't hurt the performance too much 355 // and it won't crash due to a very large scale. 356 // The drawable will look blurry above this size. 357 const static int MAX_CACHED_BITMAP_SIZE; 358 359 bool mCacheDirty = true; 360 bool mAllowCaching = true; 361 float mViewportWidth = 0; 362 float mViewportHeight = 0; 363 float mRootAlpha = 1.0f; 364 365 std::unique_ptr<Group> mRootNode; 366 SkRect mBounds; 367 SkMatrix mCanvasMatrix; 368 SkPaint mPaint; 369 SkPathMeasure mPathMeasure; 370 SkBitmap mCachedBitmap; 371 372}; 373 374} // namespace VectorDrawable 375 376typedef VectorDrawable::Path::Data PathData; 377} // namespace uirenderer 378} // namespace android 379 380#endif // ANDROID_HWUI_VPATH_H 381