• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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