OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkMatrix.h" | 8 #include "SkMatrix.h" |
9 #include "SkOpEdgeBuilder.h" | 9 #include "SkOpEdgeBuilder.h" |
10 #include "SkPathPriv.h" | 10 #include "SkPathPriv.h" |
11 #include "SkPathOps.h" | 11 #include "SkPathOps.h" |
12 #include "SkPathOpsCommon.h" | 12 #include "SkPathOpsCommon.h" |
13 | 13 |
14 static bool one_contour(const SkPath& path) { | 14 static bool one_contour(const SkPath& path) { |
15 SkChunkAlloc allocator(256); | 15 SkChunkAlloc allocator(256); |
16 int verbCount = path.countVerbs(); | 16 int verbCount = path.countVerbs(); |
17 uint8_t* verbs = (uint8_t*) allocator.alloc(sizeof(uint8_t) * verbCount, | 17 uint8_t* verbs = (uint8_t*) allocator.alloc(sizeof(uint8_t) * verbCount, |
18 SkChunkAlloc::kThrow_AllocFailType); | 18 SkChunkAlloc::kThrow_AllocFailType); |
19 (void) path.getVerbs(verbs, verbCount); | 19 (void) path.getVerbs(verbs, verbCount); |
20 for (int index = 1; index < verbCount; ++index) { | 20 for (int index = 1; index < verbCount; ++index) { |
21 if (verbs[index] == SkPath::kMove_Verb) { | 21 if (verbs[index] == SkPath::kMove_Verb) { |
22 return false; | 22 return false; |
23 } | 23 } |
24 } | 24 } |
25 return true; | 25 return true; |
26 } | 26 } |
27 | 27 |
28 void SkOpBuilder::ReversePath(SkPath* path) { | 28 bool FixWinding(SkPath* path) { |
29 SkPath temp; | |
30 SkPoint lastPt; | |
31 SkAssertResult(path->getLastPt(&lastPt)); | |
32 temp.moveTo(lastPt); | |
33 temp.reversePathTo(*path); | |
34 temp.close(); | |
35 *path = temp; | |
36 } | |
37 | |
38 bool SkOpBuilder::FixWinding(SkPath* path) { | |
39 SkPath::FillType fillType = path->getFillType(); | 29 SkPath::FillType fillType = path->getFillType(); |
40 if (fillType == SkPath::kInverseEvenOdd_FillType) { | 30 if (fillType == SkPath::kInverseEvenOdd_FillType) { |
41 fillType = SkPath::kInverseWinding_FillType; | 31 fillType = SkPath::kInverseWinding_FillType; |
42 } else if (fillType == SkPath::kEvenOdd_FillType) { | 32 } else if (fillType == SkPath::kEvenOdd_FillType) { |
43 fillType = SkPath::kWinding_FillType; | 33 fillType = SkPath::kWinding_FillType; |
44 } | 34 } |
45 SkPathPriv::FirstDirection dir; | 35 SkPathPriv::FirstDirection dir; |
46 if (one_contour(*path) && SkPathPriv::CheapComputeFirstDirection(*path, &dir
)) { | 36 if (one_contour(*path) && SkPathPriv::CheapComputeFirstDirection(*path, &dir
)) { |
47 if (dir != SkPathPriv::kCCW_FirstDirection) { | 37 if (dir != SkPathPriv::kCCW_FirstDirection) { |
48 ReversePath(path); | 38 SkPath temp; |
| 39 temp.reverseAddPath(*path); |
| 40 *path = temp; |
49 } | 41 } |
50 path->setFillType(fillType); | 42 path->setFillType(fillType); |
51 return true; | 43 return true; |
52 } | 44 } |
53 SkChunkAlloc allocator(4096); | 45 SkChunkAlloc allocator(4096); |
54 SkOpContourHead contourHead; | 46 SkOpContourHead contourHead; |
55 SkOpGlobalState globalState(&contourHead, &allocator SkDEBUGPARAMS(false) | 47 SkOpGlobalState globalState(&contourHead, &allocator SkDEBUGPARAMS(false) |
56 SkDEBUGPARAMS(nullptr)); | 48 SkDEBUGPARAMS(nullptr)); |
57 SkOpEdgeBuilder builder(*path, &contourHead, &globalState); | 49 SkOpEdgeBuilder builder(*path, &contourHead, &globalState); |
58 if (builder.unparseable() || !builder.finish()) { | 50 if (builder.unparseable() || !builder.finish()) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 // If all paths are convex, track direction, reversing as needed. | 126 // If all paths are convex, track direction, reversing as needed. |
135 if (test->isConvex()) { | 127 if (test->isConvex()) { |
136 SkPathPriv::FirstDirection dir; | 128 SkPathPriv::FirstDirection dir; |
137 if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) { | 129 if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) { |
138 allUnion = false; | 130 allUnion = false; |
139 break; | 131 break; |
140 } | 132 } |
141 if (firstDir == SkPathPriv::kUnknown_FirstDirection) { | 133 if (firstDir == SkPathPriv::kUnknown_FirstDirection) { |
142 firstDir = dir; | 134 firstDir = dir; |
143 } else if (firstDir != dir) { | 135 } else if (firstDir != dir) { |
144 ReversePath(test); | 136 SkPath temp; |
| 137 temp.reverseAddPath(*test); |
| 138 *test = temp; |
145 } | 139 } |
146 continue; | 140 continue; |
147 } | 141 } |
148 // If the path is not convex but its bounds do not intersect the others,
simplify is enough. | 142 // If the path is not convex but its bounds do not intersect the others,
simplify is enough. |
149 const SkRect& testBounds = test->getBounds(); | 143 const SkRect& testBounds = test->getBounds(); |
150 for (int inner = 0; inner < index; ++inner) { | 144 for (int inner = 0; inner < index; ++inner) { |
151 // OPTIMIZE: check to see if the contour bounds do not intersect oth
er contour bounds? | 145 // OPTIMIZE: check to see if the contour bounds do not intersect oth
er contour bounds? |
152 if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) { | 146 if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) { |
153 allUnion = false; | 147 allUnion = false; |
154 break; | 148 break; |
(...skipping 28 matching lines...) Expand all Loading... |
183 sum.addPath(fPathRefs[index]); | 177 sum.addPath(fPathRefs[index]); |
184 } | 178 } |
185 } | 179 } |
186 reset(); | 180 reset(); |
187 bool success = Simplify(sum, result); | 181 bool success = Simplify(sum, result); |
188 if (!success) { | 182 if (!success) { |
189 *result = original; | 183 *result = original; |
190 } | 184 } |
191 return success; | 185 return success; |
192 } | 186 } |
OLD | NEW |