Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Side by Side Diff: src/pathops/SkPathOpsOp.cpp

Issue 1111333002: compute initial winding from projected rays (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: add missing test reference Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkPathOpsLine.h ('k') | src/pathops/SkPathOpsPoint.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 Google Inc. 2 * Copyright 2012 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 #include "SkAddIntersections.h" 7 #include "SkAddIntersections.h"
8 #include "SkOpCoincidence.h" 8 #include "SkOpCoincidence.h"
9 #include "SkOpEdgeBuilder.h" 9 #include "SkOpEdgeBuilder.h"
10 #include "SkPathOpsCommon.h" 10 #include "SkPathOpsCommon.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 *chase.insert(0) = span; 91 *chase.insert(0) = span;
92 #else 92 #else
93 *chase.append() = span; 93 *chase.append() = span;
94 #endif 94 #endif
95 return first; 95 return first;
96 } 96 }
97 } 97 }
98 return NULL; 98 return NULL;
99 } 99 }
100 100
101 static bool bridgeOp(SkTDArray<SkOpContour* >& contourList, const SkPathOp op, 101 static bool bridgeOp(SkOpContourHead* contourList, const SkPathOp op,
102 const int xorMask, const int xorOpMask, SkPathWriter* simple, SkChunkAll oc* allocator) { 102 const int xorMask, const int xorOpMask, SkPathWriter* simple, SkChunkAll oc* allocator) {
103 bool firstContour = true;
104 bool unsortable = false; 103 bool unsortable = false;
105 bool topUnsortable = false;
106 bool firstPass = true;
107 SkDPoint lastTopLeft;
108 SkDPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
109 do { 104 do {
110 SkOpSpanBase* start = NULL; 105 SkOpSpan* span = FindSortableTop(contourList);
111 SkOpSpanBase* end = NULL; 106 if (!span) {
112 bool topDone;
113 bool onlyVertical = false;
114 lastTopLeft = topLeft;
115 SkOpSegment* current = FindSortableTop(contourList, firstPass, SkOpAngle ::kBinarySingle,
116 &firstContour, &start, &end, &topLeft, &topUnsortable, &topDone, &onlyVertical,
117 allocator);
118 if (!current) {
119 if ((!topUnsortable || firstPass) && !topDone) {
120 SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMi n);
121 if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_Scala rMin) {
122 if (firstPass) {
123 firstPass = false;
124 } else {
125 break;
126 }
127 }
128 topLeft.fX = topLeft.fY = SK_ScalarMin;
129 continue;
130 }
131 break;
132 } else if (onlyVertical) {
133 break; 107 break;
134 } 108 }
135 firstPass = !topUnsortable || lastTopLeft != topLeft; 109 SkOpSegment* current = span->segment();
110 SkOpSpanBase* start = span->next();
111 SkOpSpanBase* end = span;
136 SkTDArray<SkOpSpanBase*> chase; 112 SkTDArray<SkOpSpanBase*> chase;
137 do { 113 do {
138 if (current->activeOp(start, end, xorMask, xorOpMask, op)) { 114 if (current->activeOp(start, end, xorMask, xorOpMask, op)) {
139 do { 115 do {
140 if (!unsortable && current->done()) { 116 if (!unsortable && current->done()) {
141 break; 117 break;
142 } 118 }
143 SkASSERT(unsortable || !current->done()); 119 SkASSERT(unsortable || !current->done());
144 SkOpSpanBase* nextStart = start; 120 SkOpSpanBase* nextStart = start;
145 SkOpSpanBase* nextEnd = end; 121 SkOpSpanBase* nextEnd = end;
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 fprintf(file, " path.reset();\n"); 229 fprintf(file, " path.reset();\n");
254 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillT ype()); 230 fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillT ype());
255 dump_path(file, two, false, true); 231 dump_path(file, two, false, true);
256 fprintf(file, " SkPath path2(path);\n"); 232 fprintf(file, " SkPath path2(path);\n");
257 fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filenam e);\n", op); 233 fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filenam e);\n", op);
258 fprintf(file, "}\n"); 234 fprintf(file, "}\n");
259 fclose(file); 235 fclose(file);
260 } 236 }
261 #endif 237 #endif
262 238
263 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) { 239 bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
240 bool expectSuccess) {
264 SkChunkAlloc allocator(4096); // FIXME: add a constant expression here, tun e 241 SkChunkAlloc allocator(4096); // FIXME: add a constant expression here, tun e
265 SkOpContour contour; 242 SkOpContour contour;
243 SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
266 SkOpCoincidence coincidence; 244 SkOpCoincidence coincidence;
267 SkOpGlobalState globalState(&coincidence SkDEBUGPARAMS(&contour)); 245 SkOpGlobalState globalState(&coincidence, contourList);
268 #if DEBUGGING_PATHOPS_FROM_HOST 246 #if DEBUGGING_PATHOPS_FROM_HOST
269 dump_op(one, two, op); 247 dump_op(one, two, op);
270 #endif 248 #endif
271 #if 0 && DEBUG_SHOW_TEST_NAME 249 #if 0 && DEBUG_SHOW_TEST_NAME
272 char* debugName = DEBUG_FILENAME_STRING; 250 char* debugName = DEBUG_FILENAME_STRING;
273 if (debugName && debugName[0]) { 251 if (debugName && debugName[0]) {
274 SkPathOpsDebug::BumpTestName(debugName); 252 SkPathOpsDebug::BumpTestName(debugName);
275 SkPathOpsDebug::ShowPath(one, two, op, debugName); 253 SkPathOpsDebug::ShowPath(one, two, op, debugName);
276 } 254 }
277 #endif 255 #endif
278 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()]; 256 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()];
279 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI nverseFillType()] 257 SkPath::FillType fillType = gOutInverse[op][one.isInverseFillType()][two.isI nverseFillType()]
280 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType; 258 ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType;
281 const SkPath* minuend = &one; 259 const SkPath* minuend = &one;
282 const SkPath* subtrahend = &two; 260 const SkPath* subtrahend = &two;
283 if (op == kReverseDifference_SkPathOp) { 261 if (op == kReverseDifference_SkPathOp) {
284 minuend = &two; 262 minuend = &two;
285 subtrahend = &one; 263 subtrahend = &one;
286 op = kDifference_SkPathOp; 264 op = kDifference_SkPathOp;
287 } 265 }
288 #if DEBUG_SORT || DEBUG_SWAP_TOP 266 #if DEBUG_SORT
289 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault; 267 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
290 #endif 268 #endif
291 // turn path into list of segments 269 // turn path into list of segments
292 SkOpEdgeBuilder builder(*minuend, &contour, &allocator, &globalState); 270 SkOpEdgeBuilder builder(*minuend, &contour, &allocator, &globalState);
293 if (builder.unparseable()) { 271 if (builder.unparseable()) {
294 return false; 272 return false;
295 } 273 }
296 const int xorMask = builder.xorMask(); 274 const int xorMask = builder.xorMask();
297 builder.addOperand(*subtrahend); 275 builder.addOperand(*subtrahend);
298 if (!builder.finish(&allocator)) { 276 if (!builder.finish(&allocator)) {
299 return false; 277 return false;
300 } 278 }
301 #if DEBUG_DUMP_SEGMENTS 279 #if DEBUG_DUMP_SEGMENTS
302 contour.dumpSegments(op); 280 contour.dumpSegments(op);
303 #endif 281 #endif
304 282
305 const int xorOpMask = builder.xorMask(); 283 const int xorOpMask = builder.xorMask();
306 SkTDArray<SkOpContour* > contourList; 284 if (!SortContourList(&contourList, xorMask == kEvenOdd_PathOpsMask,
307 MakeContourList(&contour, contourList, xorMask == kEvenOdd_PathOpsMask, 285 xorOpMask == kEvenOdd_PathOpsMask)) {
308 xorOpMask == kEvenOdd_PathOpsMask);
309 SkOpContour** currentPtr = contourList.begin();
310 if (!currentPtr) {
311 result->reset(); 286 result->reset();
312 result->setFillType(fillType); 287 result->setFillType(fillType);
313 return true; 288 return true;
314 } 289 }
315 if ((*currentPtr)->count() == 0) {
316 SkASSERT((*currentPtr)->next() == NULL);
317 result->reset();
318 result->setFillType(fillType);
319 return true;
320 }
321 SkOpContour** listEnd = contourList.end();
322 // find all intersections between segments 290 // find all intersections between segments
291 SkOpContour* current = contourList;
323 do { 292 do {
324 SkOpContour** nextPtr = currentPtr; 293 SkOpContour* next = current;
325 SkOpContour* current = *currentPtr++; 294 while (AddIntersectTs(current, next, &coincidence, &allocator)
326 SkOpContour* next; 295 && (next = next->next()))
327 do { 296 ;
328 next = *nextPtr++; 297 } while ((current = current->next()));
329 } while (AddIntersectTs(current, next, &coincidence, &allocator) && next Ptr != listEnd);
330 } while (currentPtr != listEnd);
331 #if DEBUG_VALIDATE 298 #if DEBUG_VALIDATE
332 globalState.setPhase(SkOpGlobalState::kWalking); 299 globalState.setPhase(SkOpGlobalState::kWalking);
333 #endif 300 #endif
334 // eat through coincident edges 301 if (!HandleCoincidence(contourList, &coincidence, &allocator)) {
335 if (!HandleCoincidence(&contourList, &coincidence, &allocator, &globalState) ) {
336 return false; 302 return false;
337 } 303 }
338 // construct closed contours 304 // construct closed contours
339 result->reset(); 305 result->reset();
340 result->setFillType(fillType); 306 result->setFillType(fillType);
341 SkPathWriter wrapper(*result); 307 SkPathWriter wrapper(*result);
342 bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper, &allocator); 308 bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper, &allocator);
343 { // if some edges could not be resolved, assemble remaining fragments 309 { // if some edges could not be resolved, assemble remaining fragments
344 SkPath temp; 310 SkPath temp;
345 temp.setFillType(fillType); 311 temp.setFillType(fillType);
346 SkPathWriter assembled(temp); 312 SkPathWriter assembled(temp);
347 Assemble(wrapper, &assembled); 313 Assemble(wrapper, &assembled);
348 *result = *assembled.nativePath(); 314 *result = *assembled.nativePath();
349 result->setFillType(fillType); 315 result->setFillType(fillType);
350 } 316 }
351 return true; 317 return true;
352 } 318 }
319
320 bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
321 return OpDebug(one, two, op, result, true);
322 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsLine.h ('k') | src/pathops/SkPathOpsPoint.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698