blob: 89c1e6572f44dd117f06aa37cbde29050f4cebf9 [file] [log] [blame]
reed026beb52015-06-10 14:23:15 -07001/*
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
13class SkPathPriv {
14public:
Cary Clarkb2015442017-09-14 10:31:36 -040015#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
reed026beb52015-06-10 14:23:15 -070021 enum FirstDirection {
22 kCW_FirstDirection, // == SkPath::kCW_Direction
23 kCCW_FirstDirection, // == SkPath::kCCW_Direction
24 kUnknown_FirstDirection,
25 };
26
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 */
36 static FirstDirection OppositeFirstDirection(FirstDirection dir) {
37 static const FirstDirection gOppositeDir[] = {
halcanary9d524f22016-03-29 09:03:52 -070038 kCCW_FirstDirection, kCW_FirstDirection, kUnknown_FirstDirection,
reed026beb52015-06-10 14:23:15 -070039 };
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 */
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
ethannicholasc88cb892015-12-15 11:01:12 -080064 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;
fmalitabd5d7e72015-06-26 07:18:24 -070087 }
senorblanco84cd6212015-08-04 10:01:58 -070088
89 static void AddGenIDChangeListener(const SkPath& path, SkPathRef::GenIDChangeListener* listener) {
90 path.fPathRef->addGenIDChangeListener(listener);
91 }
bsalomonedc743a2016-06-01 09:42:31 -070092
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);
bsalomon21af9ca2016-08-25 12:29:23 -0700100
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);
bsalomon67fa4e32016-09-21 08:26:57 -0700107
108 /**
Chris Dalton1b0126b2017-06-15 11:41:37 -0600109 * 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:
117 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 };
124 Iter begin() { return Iter{fPathRef->verbs() - 1}; }
125 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 /**
bsalomon67fa4e32016-09-21 08:26:57 -0700133 * 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 */
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 */
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 */
146 static int ConicWeightCnt(const SkPath& path) {
147 return path.fPathRef->countWeights();
148 }
149
150 /** Returns a raw pointer to the path conic weights. */
151 static const SkScalar* ConicWeightData(const SkPath& path) {
152 return path.fPathRef->conicWeights();
153 }
reed026beb52015-06-10 14:23:15 -0700154};
155
156#endif