blob: 8689dee197934473f34a346a164f936c1d547dee [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:
15 enum FirstDirection {
16 kCW_FirstDirection, // == SkPath::kCW_Direction
17 kCCW_FirstDirection, // == SkPath::kCCW_Direction
18 kUnknown_FirstDirection,
19 };
20
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 */
30 static FirstDirection OppositeFirstDirection(FirstDirection dir) {
31 static const FirstDirection gOppositeDir[] = {
halcanary9d524f22016-03-29 09:03:52 -070032 kCCW_FirstDirection, kCW_FirstDirection, kUnknown_FirstDirection,
reed026beb52015-06-10 14:23:15 -070033 };
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 */
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
ethannicholasc88cb892015-12-15 11:01:12 -080058 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;
fmalitabd5d7e72015-06-26 07:18:24 -070081 }
senorblanco84cd6212015-08-04 10:01:58 -070082
83 static void AddGenIDChangeListener(const SkPath& path, SkPathRef::GenIDChangeListener* listener) {
84 path.fPathRef->addGenIDChangeListener(listener);
85 }
bsalomonedc743a2016-06-01 09:42:31 -070086
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);
reed026beb52015-06-10 14:23:15 -070094};
95
96#endif