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