OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
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 "SkBuffer.h" | 8 #include "SkBuffer.h" |
9 #include "SkErrorInternals.h" | 9 #include "SkErrorInternals.h" |
10 #include "SkGeometry.h" | 10 #include "SkGeometry.h" |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 SkPoint first, last; | 389 SkPoint first, last; |
390 const SkPoint* pts = *ptsPtr; | 390 const SkPoint* pts = *ptsPtr; |
391 const SkPoint* savePts = NULL; | 391 const SkPoint* savePts = NULL; |
392 first.set(0, 0); | 392 first.set(0, 0); |
393 last.set(0, 0); | 393 last.set(0, 0); |
394 int firstDirection = 0; | 394 int firstDirection = 0; |
395 int lastDirection = 0; | 395 int lastDirection = 0; |
396 int nextDirection = 0; | 396 int nextDirection = 0; |
397 bool closedOrMoved = false; | 397 bool closedOrMoved = false; |
398 bool autoClose = false; | 398 bool autoClose = false; |
| 399 bool insertClose = false; |
399 int verbCnt = fPathRef->countVerbs(); | 400 int verbCnt = fPathRef->countVerbs(); |
400 while (*currVerb < verbCnt && (!allowPartial || !autoClose)) { | 401 while (*currVerb < verbCnt && (!allowPartial || !autoClose)) { |
401 switch (fPathRef->atVerb(*currVerb)) { | 402 uint8_t verb = insertClose ? (uint8_t) kClose_Verb : fPathRef->atVerb(*c
urrVerb); |
| 403 switch (verb) { |
402 case kClose_Verb: | 404 case kClose_Verb: |
403 savePts = pts; | 405 savePts = pts; |
404 pts = *ptsPtr; | 406 pts = *ptsPtr; |
405 autoClose = true; | 407 autoClose = true; |
| 408 insertClose = false; |
406 case kLine_Verb: { | 409 case kLine_Verb: { |
407 SkScalar left = last.fX; | 410 SkScalar left = last.fX; |
408 SkScalar top = last.fY; | 411 SkScalar top = last.fY; |
409 SkScalar right = pts->fX; | 412 SkScalar right = pts->fX; |
410 SkScalar bottom = pts->fY; | 413 SkScalar bottom = pts->fY; |
411 ++pts; | 414 ++pts; |
412 if (left != right && top != bottom) { | 415 if (left != right && top != bottom) { |
413 return false; // diagonal | 416 return false; // diagonal |
414 } | 417 } |
415 if (left == right && top == bottom) { | 418 if (left == right && top == bottom) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 if ((directionCycle ^ turn) != nextDirection) { | 451 if ((directionCycle ^ turn) != nextDirection) { |
449 return false; // direction didn't follow cycle | 452 return false; // direction didn't follow cycle |
450 } | 453 } |
451 break; | 454 break; |
452 } | 455 } |
453 case kQuad_Verb: | 456 case kQuad_Verb: |
454 case kConic_Verb: | 457 case kConic_Verb: |
455 case kCubic_Verb: | 458 case kCubic_Verb: |
456 return false; // quadratic, cubic not allowed | 459 return false; // quadratic, cubic not allowed |
457 case kMove_Verb: | 460 case kMove_Verb: |
| 461 if (allowPartial && !autoClose && firstDirection) { |
| 462 insertClose = true; |
| 463 *currVerb -= 1; // try move again afterwards |
| 464 goto addMissingClose; |
| 465 } |
458 last = *pts++; | 466 last = *pts++; |
459 closedOrMoved = true; | 467 closedOrMoved = true; |
460 break; | 468 break; |
461 default: | 469 default: |
462 SkDEBUGFAIL("unexpected verb"); | 470 SkDEBUGFAIL("unexpected verb"); |
463 break; | 471 break; |
464 } | 472 } |
465 *currVerb += 1; | 473 *currVerb += 1; |
466 lastDirection = nextDirection; | 474 lastDirection = nextDirection; |
| 475 addMissingClose: |
| 476 ; |
467 } | 477 } |
468 // Success if 4 corners and first point equals last | 478 // Success if 4 corners and first point equals last |
469 bool result = 4 == corners && (first == last || autoClose); | 479 bool result = 4 == corners && (first == last || autoClose); |
470 if (!result) { | 480 if (!result) { |
471 // check if we are just an incomplete rectangle, in which case we can | 481 // check if we are just an incomplete rectangle, in which case we can |
472 // return true, but not claim to be closed. | 482 // return true, but not claim to be closed. |
473 // e.g. | 483 // e.g. |
474 // 3 sided rectangle | 484 // 3 sided rectangle |
475 // 4 sided but the last edge is not long enough to reach the start | 485 // 4 sided but the last edge is not long enough to reach the start |
476 // | 486 // |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 if (num) { | 521 if (num) { |
512 rect->set(first, num); | 522 rect->set(first, num); |
513 } else { | 523 } else { |
514 // 'pts' isn't updated for open rects | 524 // 'pts' isn't updated for open rects |
515 *rect = this->getBounds(); | 525 *rect = this->getBounds(); |
516 } | 526 } |
517 } | 527 } |
518 return true; | 528 return true; |
519 } | 529 } |
520 | 530 |
521 bool SkPath::isNestedRects(SkRect rects[2], Direction dirs[2]) const { | 531 bool SkPath::isNestedFillRects(SkRect rects[2], Direction dirs[2]) const { |
522 SkDEBUGCODE(this->validate();) | 532 SkDEBUGCODE(this->validate();) |
523 int currVerb = 0; | 533 int currVerb = 0; |
524 const SkPoint* pts = fPathRef->points(); | 534 const SkPoint* pts = fPathRef->points(); |
525 const SkPoint* first = pts; | 535 const SkPoint* first = pts; |
526 Direction testDirs[2]; | 536 Direction testDirs[2]; |
527 if (!isRectContour(true, &currVerb, &pts, NULL, &testDirs[0])) { | 537 if (!isRectContour(true, &currVerb, &pts, NULL, &testDirs[0])) { |
528 return false; | 538 return false; |
529 } | 539 } |
530 const SkPoint* last = pts; | 540 const SkPoint* last = pts; |
531 SkRect testRects[2]; | 541 SkRect testRects[2]; |
532 if (isRectContour(false, &currVerb, &pts, NULL, &testDirs[1])) { | 542 bool isClosed; |
| 543 if (isRectContour(false, &currVerb, &pts, &isClosed, &testDirs[1])) { |
533 testRects[0].set(first, SkToS32(last - first)); | 544 testRects[0].set(first, SkToS32(last - first)); |
| 545 if (!isClosed) { |
| 546 pts = fPathRef->points() + fPathRef->countPoints(); |
| 547 } |
534 testRects[1].set(last, SkToS32(pts - last)); | 548 testRects[1].set(last, SkToS32(pts - last)); |
535 if (testRects[0].contains(testRects[1])) { | 549 if (testRects[0].contains(testRects[1])) { |
536 if (rects) { | 550 if (rects) { |
537 rects[0] = testRects[0]; | 551 rects[0] = testRects[0]; |
538 rects[1] = testRects[1]; | 552 rects[1] = testRects[1]; |
539 } | 553 } |
540 if (dirs) { | 554 if (dirs) { |
541 dirs[0] = testDirs[0]; | 555 dirs[0] = testDirs[0]; |
542 dirs[1] = testDirs[1]; | 556 dirs[1] = testDirs[1]; |
543 } | 557 } |
(...skipping 2220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2764 switch (this->getFillType()) { | 2778 switch (this->getFillType()) { |
2765 case SkPath::kEvenOdd_FillType: | 2779 case SkPath::kEvenOdd_FillType: |
2766 case SkPath::kInverseEvenOdd_FillType: | 2780 case SkPath::kInverseEvenOdd_FillType: |
2767 w &= 1; | 2781 w &= 1; |
2768 break; | 2782 break; |
2769 default: | 2783 default: |
2770 break; | 2784 break; |
2771 } | 2785 } |
2772 return SkToBool(w); | 2786 return SkToBool(w); |
2773 } | 2787 } |
OLD | NEW |