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 bool FixWinding(SkPath* path) { | 28 void SkOpBuilder::ReversePath(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) { |
29 SkPath::FillType fillType = path->getFillType(); | 39 SkPath::FillType fillType = path->getFillType(); |
30 if (fillType == SkPath::kInverseEvenOdd_FillType) { | 40 if (fillType == SkPath::kInverseEvenOdd_FillType) { |
31 fillType = SkPath::kInverseWinding_FillType; | 41 fillType = SkPath::kInverseWinding_FillType; |
32 } else if (fillType == SkPath::kEvenOdd_FillType) { | 42 } else if (fillType == SkPath::kEvenOdd_FillType) { |
33 fillType = SkPath::kWinding_FillType; | 43 fillType = SkPath::kWinding_FillType; |
34 } | 44 } |
35 SkPathPriv::FirstDirection dir; | 45 SkPathPriv::FirstDirection dir; |
36 if (one_contour(*path) && SkPathPriv::CheapComputeFirstDirection(*path, &dir
)) { | 46 if (one_contour(*path) && SkPathPriv::CheapComputeFirstDirection(*path, &dir
)) { |
37 if (dir != SkPathPriv::kCCW_FirstDirection) { | 47 if (dir != SkPathPriv::kCCW_FirstDirection) { |
38 SkPath temp; | 48 ReversePath(path); |
39 temp.reverseAddPath(*path); | |
40 *path = temp; | |
41 } | 49 } |
42 path->setFillType(fillType); | 50 path->setFillType(fillType); |
43 return true; | 51 return true; |
44 } | 52 } |
45 SkChunkAlloc allocator(4096); | 53 SkChunkAlloc allocator(4096); |
46 SkOpContourHead contourHead; | 54 SkOpContourHead contourHead; |
47 SkOpGlobalState globalState(&contourHead, &allocator SkDEBUGPARAMS(false) | 55 SkOpGlobalState globalState(&contourHead, &allocator SkDEBUGPARAMS(false) |
48 SkDEBUGPARAMS(nullptr)); | 56 SkDEBUGPARAMS(nullptr)); |
49 SkOpEdgeBuilder builder(*path, &contourHead, &globalState); | 57 SkOpEdgeBuilder builder(*path, &contourHead, &globalState); |
50 if (builder.unparseable() || !builder.finish()) { | 58 if (builder.unparseable() || !builder.finish()) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 // If all paths are convex, track direction, reversing as needed. | 134 // If all paths are convex, track direction, reversing as needed. |
127 if (test->isConvex()) { | 135 if (test->isConvex()) { |
128 SkPathPriv::FirstDirection dir; | 136 SkPathPriv::FirstDirection dir; |
129 if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) { | 137 if (!SkPathPriv::CheapComputeFirstDirection(*test, &dir)) { |
130 allUnion = false; | 138 allUnion = false; |
131 break; | 139 break; |
132 } | 140 } |
133 if (firstDir == SkPathPriv::kUnknown_FirstDirection) { | 141 if (firstDir == SkPathPriv::kUnknown_FirstDirection) { |
134 firstDir = dir; | 142 firstDir = dir; |
135 } else if (firstDir != dir) { | 143 } else if (firstDir != dir) { |
136 SkPath temp; | 144 ReversePath(test); |
137 temp.reverseAddPath(*test); | |
138 *test = temp; | |
139 } | 145 } |
140 continue; | 146 continue; |
141 } | 147 } |
142 // If the path is not convex but its bounds do not intersect the others,
simplify is enough. | 148 // If the path is not convex but its bounds do not intersect the others,
simplify is enough. |
143 const SkRect& testBounds = test->getBounds(); | 149 const SkRect& testBounds = test->getBounds(); |
144 for (int inner = 0; inner < index; ++inner) { | 150 for (int inner = 0; inner < index; ++inner) { |
145 // OPTIMIZE: check to see if the contour bounds do not intersect oth
er contour bounds? | 151 // OPTIMIZE: check to see if the contour bounds do not intersect oth
er contour bounds? |
146 if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) { | 152 if (SkRect::Intersects(fPathRefs[inner].getBounds(), testBounds)) { |
147 allUnion = false; | 153 allUnion = false; |
148 break; | 154 break; |
(...skipping 28 matching lines...) Expand all Loading... |
177 sum.addPath(fPathRefs[index]); | 183 sum.addPath(fPathRefs[index]); |
178 } | 184 } |
179 } | 185 } |
180 reset(); | 186 reset(); |
181 bool success = Simplify(sum, result); | 187 bool success = Simplify(sum, result); |
182 if (!success) { | 188 if (!success) { |
183 *result = original; | 189 *result = original; |
184 } | 190 } |
185 return success; | 191 return success; |
186 } | 192 } |
OLD | NEW |