| 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 |