| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkBuffer.h" | 10 #include "SkBuffer.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 | 115 |
| 116 The iterator does more cleanup, especially if forceClose == true | 116 The iterator does more cleanup, especially if forceClose == true |
| 117 1. If we encounter degenerate segments, remove them | 117 1. If we encounter degenerate segments, remove them |
| 118 2. if we encounter Close, return a cons'd up Line() first (if the curr-pt !=
start-pt) | 118 2. if we encounter Close, return a cons'd up Line() first (if the curr-pt !=
start-pt) |
| 119 3. if we encounter Move without a preceeding Close, and forceClose is true,
goto #2 | 119 3. if we encounter Move without a preceeding Close, and forceClose is true,
goto #2 |
| 120 4. if we encounter Line | Quad | Cubic after Close, cons up a Move | 120 4. if we encounter Line | Quad | Cubic after Close, cons up a Move |
| 121 */ | 121 */ |
| 122 | 122 |
| 123 //////////////////////////////////////////////////////////////////////////// | 123 //////////////////////////////////////////////////////////////////////////// |
| 124 | 124 |
| 125 // flag to require a moveTo if we begin with something else, like lineTo etc. | |
| 126 #define INITIAL_LASTMOVETOINDEX_VALUE ~0 | |
| 127 | |
| 128 SkPath::SkPath() | 125 SkPath::SkPath() |
| 129 : fPathRef(SkPathRef::CreateEmpty()) | 126 : fPathRef(SkPathRef::CreateEmpty()) |
| 130 #ifdef SK_BUILD_FOR_ANDROID | 127 #ifdef SK_BUILD_FOR_ANDROID |
| 131 , fSourcePath(NULL) | 128 , fSourcePath(NULL) |
| 132 #endif | 129 #endif |
| 133 { | 130 { |
| 134 this->resetFields(); | 131 this->resetFields(); |
| 135 } | 132 } |
| 136 | 133 |
| 137 void SkPath::resetFields() { | 134 void SkPath::resetFields() { |
| 138 //fPathRef is assumed to have been emptied by the caller. | 135 //fPathRef is assumed to have been emptied by the caller. |
| 139 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; | |
| 140 fFillType = kWinding_FillType; | 136 fFillType = kWinding_FillType; |
| 141 fConvexity = kUnknown_Convexity; | 137 fConvexity = kUnknown_Convexity; |
| 142 fDirection = kUnknown_Direction; | 138 fDirection = kUnknown_Direction; |
| 143 | 139 |
| 144 // We don't touch Android's fSourcePath. It's used to track texture garbage
collection, so we | 140 // We don't touch Android's fSourcePath. It's used to track texture garbage
collection, so we |
| 145 // don't want to muck with it if it's been set to something non-NULL. | 141 // don't want to muck with it if it's been set to something non-NULL. |
| 146 } | 142 } |
| 147 | 143 |
| 148 SkPath::SkPath(const SkPath& that) | 144 SkPath::SkPath(const SkPath& that) |
| 149 : fPathRef(SkRef(that.fPathRef.get())) { | 145 : fPathRef(SkRef(that.fPathRef.get())) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 167 #ifdef SK_BUILD_FOR_ANDROID | 163 #ifdef SK_BUILD_FOR_ANDROID |
| 168 fSourcePath = that.fSourcePath; | 164 fSourcePath = that.fSourcePath; |
| 169 #endif | 165 #endif |
| 170 } | 166 } |
| 171 SkDEBUGCODE(this->validate();) | 167 SkDEBUGCODE(this->validate();) |
| 172 return *this; | 168 return *this; |
| 173 } | 169 } |
| 174 | 170 |
| 175 void SkPath::copyFields(const SkPath& that) { | 171 void SkPath::copyFields(const SkPath& that) { |
| 176 //fPathRef is assumed to have been set by the caller. | 172 //fPathRef is assumed to have been set by the caller. |
| 177 fLastMoveToIndex = that.fLastMoveToIndex; | |
| 178 fFillType = that.fFillType; | 173 fFillType = that.fFillType; |
| 179 fConvexity = that.fConvexity; | 174 fConvexity = that.fConvexity; |
| 180 fDirection = that.fDirection; | 175 fDirection = that.fDirection; |
| 181 } | 176 } |
| 182 | 177 |
| 183 bool operator==(const SkPath& a, const SkPath& b) { | 178 bool operator==(const SkPath& a, const SkPath& b) { |
| 184 // note: don't need to look at isConvex or bounds, since just comparing the | 179 // note: don't need to look at isConvex or bounds, since just comparing the |
| 185 // raw data is sufficient. | 180 // raw data is sufficient. |
| 186 return &a == &b || | 181 return &a == &b || |
| 187 (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get()); | 182 (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get()); |
| 188 } | 183 } |
| 189 | 184 |
| 190 void SkPath::swap(SkPath& that) { | 185 void SkPath::swap(SkPath& that) { |
| 191 SkASSERT(&that != NULL); | 186 SkASSERT(&that != NULL); |
| 192 | 187 |
| 193 if (this != &that) { | 188 if (this != &that) { |
| 194 fPathRef.swap(&that.fPathRef); | 189 fPathRef.swap(&that.fPathRef); |
| 195 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); | |
| 196 SkTSwap<uint8_t>(fFillType, that.fFillType); | 190 SkTSwap<uint8_t>(fFillType, that.fFillType); |
| 197 SkTSwap<uint8_t>(fConvexity, that.fConvexity); | 191 SkTSwap<uint8_t>(fConvexity, that.fConvexity); |
| 198 SkTSwap<uint8_t>(fDirection, that.fDirection); | 192 SkTSwap<uint8_t>(fDirection, that.fDirection); |
| 199 #ifdef SK_BUILD_FOR_ANDROID | 193 #ifdef SK_BUILD_FOR_ANDROID |
| 200 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath); | 194 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath); |
| 201 #endif | 195 #endif |
| 202 } | 196 } |
| 203 } | 197 } |
| 204 | 198 |
| 205 static inline bool check_edge_against_rect(const SkPoint& p0, | 199 static inline bool check_edge_against_rect(const SkPoint& p0, |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 SkDEBUGCODE(this->validate();) | 654 SkDEBUGCODE(this->validate();) |
| 661 SkPathRef::Editor(&fPathRef, inc, inc); | 655 SkPathRef::Editor(&fPathRef, inc, inc); |
| 662 SkDEBUGCODE(this->validate();) | 656 SkDEBUGCODE(this->validate();) |
| 663 } | 657 } |
| 664 | 658 |
| 665 void SkPath::moveTo(SkScalar x, SkScalar y) { | 659 void SkPath::moveTo(SkScalar x, SkScalar y) { |
| 666 SkDEBUGCODE(this->validate();) | 660 SkDEBUGCODE(this->validate();) |
| 667 | 661 |
| 668 SkPathRef::Editor ed(&fPathRef); | 662 SkPathRef::Editor ed(&fPathRef); |
| 669 | 663 |
| 670 // remember our index | |
| 671 fLastMoveToIndex = fPathRef->countPoints(); | |
| 672 | |
| 673 ed.growForVerb(kMove_Verb)->set(x, y); | 664 ed.growForVerb(kMove_Verb)->set(x, y); |
| 674 } | 665 } |
| 675 | 666 |
| 676 void SkPath::rMoveTo(SkScalar x, SkScalar y) { | 667 void SkPath::rMoveTo(SkScalar x, SkScalar y) { |
| 677 SkPoint pt; | 668 SkPoint pt; |
| 678 this->getLastPt(&pt); | 669 this->getLastPt(&pt); |
| 679 this->moveTo(pt.fX + x, pt.fY + y); | 670 this->moveTo(pt.fX + x, pt.fY + y); |
| 680 } | 671 } |
| 681 | 672 |
| 682 void SkPath::injectMoveToIfNeeded() { | |
| 683 if (fLastMoveToIndex < 0) { | |
| 684 SkScalar x, y; | |
| 685 if (fPathRef->countVerbs() == 0) { | |
| 686 x = y = 0; | |
| 687 } else { | |
| 688 const SkPoint& pt = fPathRef->atPoint(~fLastMoveToIndex); | |
| 689 x = pt.fX; | |
| 690 y = pt.fY; | |
| 691 } | |
| 692 this->moveTo(x, y); | |
| 693 } | |
| 694 } | |
| 695 | |
| 696 void SkPath::lineTo(SkScalar x, SkScalar y) { | 673 void SkPath::lineTo(SkScalar x, SkScalar y) { |
| 697 SkDEBUGCODE(this->validate();) | 674 SkDEBUGCODE(this->validate();) |
| 698 | 675 |
| 699 this->injectMoveToIfNeeded(); | |
| 700 | |
| 701 SkPathRef::Editor ed(&fPathRef); | 676 SkPathRef::Editor ed(&fPathRef); |
| 677 ed.injectMoveToIfNeeded(); |
| 702 ed.growForVerb(kLine_Verb)->set(x, y); | 678 ed.growForVerb(kLine_Verb)->set(x, y); |
| 703 | 679 |
| 704 DIRTY_AFTER_EDIT; | 680 DIRTY_AFTER_EDIT; |
| 705 } | 681 } |
| 706 | 682 |
| 707 void SkPath::rLineTo(SkScalar x, SkScalar y) { | 683 void SkPath::rLineTo(SkScalar x, SkScalar y) { |
| 708 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 684 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
| 709 SkPoint pt; | 685 SkPoint pt; |
| 710 this->getLastPt(&pt); | 686 this->getLastPt(&pt); |
| 711 this->lineTo(pt.fX + x, pt.fY + y); | 687 this->lineTo(pt.fX + x, pt.fY + y); |
| 712 } | 688 } |
| 713 | 689 |
| 714 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { | 690 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { |
| 715 SkDEBUGCODE(this->validate();) | 691 SkDEBUGCODE(this->validate();) |
| 716 | 692 |
| 717 this->injectMoveToIfNeeded(); | |
| 718 | |
| 719 SkPathRef::Editor ed(&fPathRef); | 693 SkPathRef::Editor ed(&fPathRef); |
| 694 ed.injectMoveToIfNeeded(); |
| 720 SkPoint* pts = ed.growForVerb(kQuad_Verb); | 695 SkPoint* pts = ed.growForVerb(kQuad_Verb); |
| 721 pts[0].set(x1, y1); | 696 pts[0].set(x1, y1); |
| 722 pts[1].set(x2, y2); | 697 pts[1].set(x2, y2); |
| 723 | 698 |
| 724 DIRTY_AFTER_EDIT; | 699 DIRTY_AFTER_EDIT; |
| 725 } | 700 } |
| 726 | 701 |
| 727 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { | 702 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { |
| 728 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 703 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
| 729 SkPoint pt; | 704 SkPoint pt; |
| 730 this->getLastPt(&pt); | 705 this->getLastPt(&pt); |
| 731 this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2); | 706 this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2); |
| 732 } | 707 } |
| 733 | 708 |
| 734 void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 709 void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
| 735 SkScalar w) { | 710 SkScalar w) { |
| 736 // check for <= 0 or NaN with this test | 711 // check for <= 0 or NaN with this test |
| 737 if (!(w > 0)) { | 712 if (!(w > 0)) { |
| 738 this->lineTo(x2, y2); | 713 this->lineTo(x2, y2); |
| 739 } else if (!SkScalarIsFinite(w)) { | 714 } else if (!SkScalarIsFinite(w)) { |
| 740 this->lineTo(x1, y1); | 715 this->lineTo(x1, y1); |
| 741 this->lineTo(x2, y2); | 716 this->lineTo(x2, y2); |
| 742 } else if (SK_Scalar1 == w) { | 717 } else if (SK_Scalar1 == w) { |
| 743 this->quadTo(x1, y1, x2, y2); | 718 this->quadTo(x1, y1, x2, y2); |
| 744 } else { | 719 } else { |
| 745 SkDEBUGCODE(this->validate();) | 720 SkDEBUGCODE(this->validate();) |
| 746 | 721 |
| 747 this->injectMoveToIfNeeded(); | |
| 748 | |
| 749 SkPathRef::Editor ed(&fPathRef); | 722 SkPathRef::Editor ed(&fPathRef); |
| 723 ed.injectMoveToIfNeeded(); |
| 750 SkPoint* pts = ed.growForVerb(kConic_Verb, w); | 724 SkPoint* pts = ed.growForVerb(kConic_Verb, w); |
| 751 pts[0].set(x1, y1); | 725 pts[0].set(x1, y1); |
| 752 pts[1].set(x2, y2); | 726 pts[1].set(x2, y2); |
| 753 | 727 |
| 754 DIRTY_AFTER_EDIT; | 728 DIRTY_AFTER_EDIT; |
| 755 } | 729 } |
| 756 } | 730 } |
| 757 | 731 |
| 758 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, | 732 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, |
| 759 SkScalar w) { | 733 SkScalar w) { |
| 760 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 734 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
| 761 SkPoint pt; | 735 SkPoint pt; |
| 762 this->getLastPt(&pt); | 736 this->getLastPt(&pt); |
| 763 this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w); | 737 this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w); |
| 764 } | 738 } |
| 765 | 739 |
| 766 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 740 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
| 767 SkScalar x3, SkScalar y3) { | 741 SkScalar x3, SkScalar y3) { |
| 768 SkDEBUGCODE(this->validate();) | 742 SkDEBUGCODE(this->validate();) |
| 769 | 743 |
| 770 this->injectMoveToIfNeeded(); | |
| 771 | |
| 772 SkPathRef::Editor ed(&fPathRef); | 744 SkPathRef::Editor ed(&fPathRef); |
| 745 ed.injectMoveToIfNeeded(); |
| 773 SkPoint* pts = ed.growForVerb(kCubic_Verb); | 746 SkPoint* pts = ed.growForVerb(kCubic_Verb); |
| 774 pts[0].set(x1, y1); | 747 pts[0].set(x1, y1); |
| 775 pts[1].set(x2, y2); | 748 pts[1].set(x2, y2); |
| 776 pts[2].set(x3, y3); | 749 pts[2].set(x3, y3); |
| 777 | 750 |
| 778 DIRTY_AFTER_EDIT; | 751 DIRTY_AFTER_EDIT; |
| 779 } | 752 } |
| 780 | 753 |
| 781 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 754 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
| 782 SkScalar x3, SkScalar y3) { | 755 SkScalar x3, SkScalar y3) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 803 break; | 776 break; |
| 804 } | 777 } |
| 805 case kClose_Verb: | 778 case kClose_Verb: |
| 806 // don't add a close if it's the first verb or a repeat | 779 // don't add a close if it's the first verb or a repeat |
| 807 break; | 780 break; |
| 808 default: | 781 default: |
| 809 SkDEBUGFAIL("unexpected verb"); | 782 SkDEBUGFAIL("unexpected verb"); |
| 810 break; | 783 break; |
| 811 } | 784 } |
| 812 } | 785 } |
| 813 | |
| 814 // signal that we need a moveTo to follow us (unless we're done) | |
| 815 #if 0 | |
| 816 if (fLastMoveToIndex >= 0) { | |
| 817 fLastMoveToIndex = ~fLastMoveToIndex; | |
| 818 } | |
| 819 #else | |
| 820 fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1); | |
| 821 #endif | |
| 822 } | 786 } |
| 823 | 787 |
| 824 /////////////////////////////////////////////////////////////////////////////// | 788 /////////////////////////////////////////////////////////////////////////////// |
| 825 | 789 |
| 826 static void assert_known_direction(int dir) { | 790 static void assert_known_direction(int dir) { |
| 827 SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir); | 791 SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir); |
| 828 } | 792 } |
| 829 | 793 |
| 830 void SkPath::addRect(const SkRect& rect, Direction dir) { | 794 void SkPath::addRect(const SkRect& rect, Direction dir) { |
| 831 this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir); | 795 this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 853 } | 817 } |
| 854 this->close(); | 818 this->close(); |
| 855 } | 819 } |
| 856 | 820 |
| 857 void SkPath::addPoly(const SkPoint pts[], int count, bool close) { | 821 void SkPath::addPoly(const SkPoint pts[], int count, bool close) { |
| 858 SkDEBUGCODE(this->validate();) | 822 SkDEBUGCODE(this->validate();) |
| 859 if (count <= 0) { | 823 if (count <= 0) { |
| 860 return; | 824 return; |
| 861 } | 825 } |
| 862 | 826 |
| 863 fLastMoveToIndex = fPathRef->countPoints(); | |
| 864 | |
| 865 // +close makes room for the extra kClose_Verb | 827 // +close makes room for the extra kClose_Verb |
| 866 SkPathRef::Editor ed(&fPathRef, count+close, count); | 828 SkPathRef::Editor ed(&fPathRef, count+close, count); |
| 867 | 829 |
| 868 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); | 830 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); |
| 869 if (count > 1) { | 831 if (count > 1) { |
| 870 SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1); | 832 SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1); |
| 871 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); | 833 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); |
| 872 } | 834 } |
| 873 | 835 |
| 874 if (close) { | 836 if (close) { |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); | 1313 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); |
| 1352 return; | 1314 return; |
| 1353 } | 1315 } |
| 1354 | 1316 |
| 1355 SkPoint pts[kSkBuildQuadArcStorage]; | 1317 SkPoint pts[kSkBuildQuadArcStorage]; |
| 1356 int count = build_arc_points(oval, startAngle, sweepAngle, pts); | 1318 int count = build_arc_points(oval, startAngle, sweepAngle, pts); |
| 1357 | 1319 |
| 1358 SkDEBUGCODE(this->validate();) | 1320 SkDEBUGCODE(this->validate();) |
| 1359 SkASSERT(count & 1); | 1321 SkASSERT(count & 1); |
| 1360 | 1322 |
| 1361 fLastMoveToIndex = fPathRef->countPoints(); | |
| 1362 | |
| 1363 SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count); | 1323 SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count); |
| 1364 | 1324 |
| 1365 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); | 1325 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); |
| 1366 if (count > 1) { | 1326 if (count > 1) { |
| 1367 SkPoint* p = ed.growForRepeatedVerb(kQuad_Verb, (count-1)/2); | 1327 SkPoint* p = ed.growForRepeatedVerb(kQuad_Verb, (count-1)/2); |
| 1368 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); | 1328 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); |
| 1369 } | 1329 } |
| 1370 | 1330 |
| 1371 DIRTY_AFTER_EDIT; | 1331 DIRTY_AFTER_EDIT; |
| 1372 SkDEBUGCODE(this->validate();) | 1332 SkDEBUGCODE(this->validate();) |
| (...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2881 switch (this->getFillType()) { | 2841 switch (this->getFillType()) { |
| 2882 case SkPath::kEvenOdd_FillType: | 2842 case SkPath::kEvenOdd_FillType: |
| 2883 case SkPath::kInverseEvenOdd_FillType: | 2843 case SkPath::kInverseEvenOdd_FillType: |
| 2884 w &= 1; | 2844 w &= 1; |
| 2885 break; | 2845 break; |
| 2886 default: | 2846 default: |
| 2887 break; | 2847 break; |
| 2888 } | 2848 } |
| 2889 return SkToBool(w); | 2849 return SkToBool(w); |
| 2890 } | 2850 } |
| OLD | NEW |