1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkPathPriv_DEFINED 9 #define SkPathPriv_DEFINED 10 11 #include "SkPath.h" 12 13 class SkPathPriv { 14 public: 15 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 16 static const int kPathRefGenIDBitCnt = 30; // leave room for the fill type (skbug.com/1762) 17 #else 18 static const int kPathRefGenIDBitCnt = 32; 19 #endif 20 21 enum FirstDirection { 22 kCW_FirstDirection, // == SkPath::kCW_Direction 23 kCCW_FirstDirection, // == SkPath::kCCW_Direction 24 kUnknown_FirstDirection, 25 }; 26 AsFirstDirection(SkPath::Direction dir)27 static FirstDirection AsFirstDirection(SkPath::Direction dir) { 28 // since we agree numerically for the values in Direction, we can just cast. 29 return (FirstDirection)dir; 30 } 31 32 /** 33 * Return the opposite of the specified direction. kUnknown is its own 34 * opposite. 35 */ OppositeFirstDirection(FirstDirection dir)36 static FirstDirection OppositeFirstDirection(FirstDirection dir) { 37 static const FirstDirection gOppositeDir[] = { 38 kCCW_FirstDirection, kCW_FirstDirection, kUnknown_FirstDirection, 39 }; 40 return gOppositeDir[dir]; 41 } 42 43 /** 44 * Tries to quickly compute the direction of the first non-degenerate 45 * contour. If it can be computed, return true and set dir to that 46 * direction. If it cannot be (quickly) determined, return false and ignore 47 * the dir parameter. If the direction was determined, it is cached to make 48 * subsequent calls return quickly. 49 */ 50 static bool CheapComputeFirstDirection(const SkPath&, FirstDirection* dir); 51 52 /** 53 * Returns true if the path's direction can be computed via 54 * cheapComputDirection() and if that computed direction matches the 55 * specified direction. If dir is kUnknown, returns true if the direction 56 * cannot be computed. 57 */ CheapIsFirstDirection(const SkPath & path,FirstDirection dir)58 static bool CheapIsFirstDirection(const SkPath& path, FirstDirection dir) { 59 FirstDirection computedDir = kUnknown_FirstDirection; 60 (void)CheapComputeFirstDirection(path, &computedDir); 61 return computedDir == dir; 62 } 63 IsClosedSingleContour(const SkPath & path)64 static bool IsClosedSingleContour(const SkPath& path) { 65 int verbCount = path.countVerbs(); 66 if (verbCount == 0) 67 return false; 68 int moveCount = 0; 69 auto verbs = path.fPathRef->verbs(); 70 for (int i = 0; i < verbCount; i++) { 71 switch (verbs[~i]) { // verbs are stored backwards; we use [~i] to get the i'th verb 72 case SkPath::Verb::kMove_Verb: 73 moveCount += 1; 74 if (moveCount > 1) { 75 return false; 76 } 77 break; 78 case SkPath::Verb::kClose_Verb: 79 if (i == verbCount - 1) { 80 return true; 81 } 82 return false; 83 default: break; 84 } 85 } 86 return false; 87 } 88 AddGenIDChangeListener(const SkPath & path,SkPathRef::GenIDChangeListener * listener)89 static void AddGenIDChangeListener(const SkPath& path, SkPathRef::GenIDChangeListener* listener) { 90 path.fPathRef->addGenIDChangeListener(listener); 91 } 92 93 /** 94 * This returns true for a rect that begins and ends at the same corner and has either a move 95 * followed by four lines or a move followed by 3 lines and a close. None of the parameters are 96 * optional. This does not permit degenerate line or point rectangles. 97 */ 98 static bool IsSimpleClosedRect(const SkPath& path, SkRect* rect, SkPath::Direction* direction, 99 unsigned* start); 100 101 /** 102 * Creates a path from arc params using the semantics of SkCanvas::drawArc. This function 103 * assumes empty ovals and zero sweeps have already been filtered out. 104 */ 105 static void CreateDrawArcPath(SkPath* path, const SkRect& oval, SkScalar startAngle, 106 SkScalar sweepAngle, bool useCenter, bool isFillNoPathEffect); 107 108 /** 109 * Returns a C++11-iterable object that traverses a path's verbs in order. e.g: 110 * 111 * for (SkPath::Verb verb : SkPathPriv::Verbs(path)) { 112 * ... 113 * } 114 */ 115 struct Verbs { 116 public: VerbsVerbs117 Verbs(const SkPath& path) : fPathRef(path.fPathRef.get()) {} 118 struct Iter { 119 void operator++() { --fVerb; } // verbs are laid out backwards in memory. 120 bool operator!=(const Iter& b) { return fVerb != b.fVerb; } 121 SkPath::Verb operator*() { return static_cast<SkPath::Verb>(*fVerb); } 122 const uint8_t* fVerb; 123 }; beginVerbs124 Iter begin() { return Iter{fPathRef->verbs() - 1}; } endVerbs125 Iter end() { return Iter{fPathRef->verbs() - fPathRef->countVerbs() - 1}; } 126 private: 127 Verbs(const Verbs&) = delete; 128 Verbs& operator=(const Verbs&) = delete; 129 SkPathRef* fPathRef; 130 }; 131 132 /** 133 * Returns a pointer to the verb data. Note that the verbs are stored backwards in memory and 134 * thus the returned pointer is the last verb. 135 */ VerbData(const SkPath & path)136 static const uint8_t* VerbData(const SkPath& path) { 137 return path.fPathRef->verbsMemBegin(); 138 } 139 140 /** Returns a raw pointer to the path points */ PointData(const SkPath & path)141 static const SkPoint* PointData(const SkPath& path) { 142 return path.fPathRef->points(); 143 } 144 145 /** Returns the number of conic weights in the path */ ConicWeightCnt(const SkPath & path)146 static int ConicWeightCnt(const SkPath& path) { 147 return path.fPathRef->countWeights(); 148 } 149 150 /** Returns a raw pointer to the path conic weights. */ ConicWeightData(const SkPath & path)151 static const SkScalar* ConicWeightData(const SkPath& path) { 152 return path.fPathRef->conicWeights(); 153 } 154 155 /** Returns true if the underlying SkPathRef has one single owner. */ TestingOnly_unique(const SkPath & path)156 static bool TestingOnly_unique(const SkPath& path) { 157 return path.fPathRef->unique(); 158 } 159 160 }; 161 162 #endif 163