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" |
11 #include "SkErrorInternals.h" | 11 #include "SkErrorInternals.h" |
12 #include "SkMath.h" | 12 #include "SkMath.h" |
13 #include "SkPath.h" | 13 #include "SkPath.h" |
14 #include "SkPathRef.h" | 14 #include "SkPathRef.h" |
15 #include "SkRRect.h" | 15 #include "SkRRect.h" |
16 #include "SkThread.h" | 16 #include "SkThread.h" |
17 | 17 |
18 // This value is just made-up for now. When count is 4, calling memset was much | |
19 // slower than just writing the loop. This seems odd, and hopefully in the | |
20 // future this we appear to have been a fluke... | |
21 #define MIN_COUNT_FOR_MEMSET_TO_BE_FAST 16 | |
22 | |
23 //////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////// |
24 | 19 |
25 /** | 20 /** |
26 * Path.bounds is defined to be the bounds of all the control points. | 21 * Path.bounds is defined to be the bounds of all the control points. |
27 * If we called bounds.join(r) we would skip r if r was empty, which breaks | 22 * If we called bounds.join(r) we would skip r if r was empty, which breaks |
28 * our promise. Hence we have a custom joiner that doesn't look at emptiness | 23 * our promise. Hence we have a custom joiner that doesn't look at emptiness |
29 */ | 24 */ |
30 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) { | 25 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) { |
31 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft); | 26 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft); |
32 dst->fTop = SkMinScalar(dst->fTop, src.fTop); | 27 dst->fTop = SkMinScalar(dst->fTop, src.fTop); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 , fSourcePath(NULL) | 131 , fSourcePath(NULL) |
137 #endif | 132 #endif |
138 { | 133 { |
139 this->resetFields(); | 134 this->resetFields(); |
140 } | 135 } |
141 | 136 |
142 void SkPath::resetFields() { | 137 void SkPath::resetFields() { |
143 //fPathRef is assumed to have been emptied by the caller. | 138 //fPathRef is assumed to have been emptied by the caller. |
144 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; | 139 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; |
145 fFillType = kWinding_FillType; | 140 fFillType = kWinding_FillType; |
146 fSegmentMask = 0; | |
147 fConvexity = kUnknown_Convexity; | 141 fConvexity = kUnknown_Convexity; |
148 fDirection = kUnknown_Direction; | 142 fDirection = kUnknown_Direction; |
149 | 143 |
150 // We don't touch Android's fSourcePath. It's used to track texture garbage
collection, so we | 144 // We don't touch Android's fSourcePath. It's used to track texture garbage
collection, so we |
151 // don't want to muck with it if it's been set to something non-NULL. | 145 // don't want to muck with it if it's been set to something non-NULL. |
152 } | 146 } |
153 | 147 |
154 SkPath::SkPath(const SkPath& that) | 148 SkPath::SkPath(const SkPath& that) |
155 : fPathRef(SkRef(that.fPathRef.get())) { | 149 : fPathRef(SkRef(that.fPathRef.get())) { |
156 this->copyFields(that); | 150 this->copyFields(that); |
(...skipping 18 matching lines...) Expand all Loading... |
175 #endif | 169 #endif |
176 } | 170 } |
177 SkDEBUGCODE(this->validate();) | 171 SkDEBUGCODE(this->validate();) |
178 return *this; | 172 return *this; |
179 } | 173 } |
180 | 174 |
181 void SkPath::copyFields(const SkPath& that) { | 175 void SkPath::copyFields(const SkPath& that) { |
182 //fPathRef is assumed to have been set by the caller. | 176 //fPathRef is assumed to have been set by the caller. |
183 fLastMoveToIndex = that.fLastMoveToIndex; | 177 fLastMoveToIndex = that.fLastMoveToIndex; |
184 fFillType = that.fFillType; | 178 fFillType = that.fFillType; |
185 fSegmentMask = that.fSegmentMask; | |
186 fConvexity = that.fConvexity; | 179 fConvexity = that.fConvexity; |
187 fDirection = that.fDirection; | 180 fDirection = that.fDirection; |
188 } | 181 } |
189 | 182 |
190 bool operator==(const SkPath& a, const SkPath& b) { | 183 bool operator==(const SkPath& a, const SkPath& b) { |
191 // note: don't need to look at isConvex or bounds, since just comparing the | 184 // note: don't need to look at isConvex or bounds, since just comparing the |
192 // raw data is sufficient. | 185 // raw data is sufficient. |
193 | |
194 // We explicitly check fSegmentMask as a quick-reject. We could skip it, | |
195 // since it is only a cache of info in the fVerbs, but its a fast way to | |
196 // notice a difference | |
197 | |
198 return &a == &b || | 186 return &a == &b || |
199 (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask && | 187 (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get()); |
200 *a.fPathRef.get() == *b.fPathRef.get()); | |
201 } | 188 } |
202 | 189 |
203 void SkPath::swap(SkPath& that) { | 190 void SkPath::swap(SkPath& that) { |
204 SkASSERT(&that != NULL); | 191 SkASSERT(&that != NULL); |
205 | 192 |
206 if (this != &that) { | 193 if (this != &that) { |
207 fPathRef.swap(&that.fPathRef); | 194 fPathRef.swap(&that.fPathRef); |
208 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); | 195 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); |
209 SkTSwap<uint8_t>(fFillType, that.fFillType); | 196 SkTSwap<uint8_t>(fFillType, that.fFillType); |
210 SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask); | |
211 SkTSwap<uint8_t>(fConvexity, that.fConvexity); | 197 SkTSwap<uint8_t>(fConvexity, that.fConvexity); |
212 SkTSwap<uint8_t>(fDirection, that.fDirection); | 198 SkTSwap<uint8_t>(fDirection, that.fDirection); |
213 #ifdef SK_BUILD_FOR_ANDROID | 199 #ifdef SK_BUILD_FOR_ANDROID |
214 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath); | 200 SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath); |
215 #endif | 201 #endif |
216 } | 202 } |
217 } | 203 } |
218 | 204 |
219 static inline bool check_edge_against_rect(const SkPoint& p0, | 205 static inline bool check_edge_against_rect(const SkPoint& p0, |
220 const SkPoint& p1, | 206 const SkPoint& p1, |
(...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 } | 653 } |
668 } | 654 } |
669 | 655 |
670 void SkPath::lineTo(SkScalar x, SkScalar y) { | 656 void SkPath::lineTo(SkScalar x, SkScalar y) { |
671 SkDEBUGCODE(this->validate();) | 657 SkDEBUGCODE(this->validate();) |
672 | 658 |
673 this->injectMoveToIfNeeded(); | 659 this->injectMoveToIfNeeded(); |
674 | 660 |
675 SkPathRef::Editor ed(&fPathRef); | 661 SkPathRef::Editor ed(&fPathRef); |
676 ed.growForVerb(kLine_Verb)->set(x, y); | 662 ed.growForVerb(kLine_Verb)->set(x, y); |
677 fSegmentMask |= kLine_SegmentMask; | |
678 | 663 |
679 DIRTY_AFTER_EDIT; | 664 DIRTY_AFTER_EDIT; |
680 } | 665 } |
681 | 666 |
682 void SkPath::rLineTo(SkScalar x, SkScalar y) { | 667 void SkPath::rLineTo(SkScalar x, SkScalar y) { |
683 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 668 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
684 SkPoint pt; | 669 SkPoint pt; |
685 this->getLastPt(&pt); | 670 this->getLastPt(&pt); |
686 this->lineTo(pt.fX + x, pt.fY + y); | 671 this->lineTo(pt.fX + x, pt.fY + y); |
687 } | 672 } |
688 | 673 |
689 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { | 674 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { |
690 SkDEBUGCODE(this->validate();) | 675 SkDEBUGCODE(this->validate();) |
691 | 676 |
692 this->injectMoveToIfNeeded(); | 677 this->injectMoveToIfNeeded(); |
693 | 678 |
694 SkPathRef::Editor ed(&fPathRef); | 679 SkPathRef::Editor ed(&fPathRef); |
695 SkPoint* pts = ed.growForVerb(kQuad_Verb); | 680 SkPoint* pts = ed.growForVerb(kQuad_Verb); |
696 pts[0].set(x1, y1); | 681 pts[0].set(x1, y1); |
697 pts[1].set(x2, y2); | 682 pts[1].set(x2, y2); |
698 fSegmentMask |= kQuad_SegmentMask; | |
699 | 683 |
700 DIRTY_AFTER_EDIT; | 684 DIRTY_AFTER_EDIT; |
701 } | 685 } |
702 | 686 |
703 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { | 687 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { |
704 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 688 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
705 SkPoint pt; | 689 SkPoint pt; |
706 this->getLastPt(&pt); | 690 this->getLastPt(&pt); |
707 this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2); | 691 this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2); |
708 } | 692 } |
709 | 693 |
710 void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 694 void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
711 SkScalar w) { | 695 SkScalar w) { |
712 // check for <= 0 or NaN with this test | 696 // check for <= 0 or NaN with this test |
713 if (!(w > 0)) { | 697 if (!(w > 0)) { |
714 this->lineTo(x2, y2); | 698 this->lineTo(x2, y2); |
715 } else if (!SkScalarIsFinite(w)) { | 699 } else if (!SkScalarIsFinite(w)) { |
716 this->lineTo(x1, y1); | 700 this->lineTo(x1, y1); |
717 this->lineTo(x2, y2); | 701 this->lineTo(x2, y2); |
718 } else if (SK_Scalar1 == w) { | 702 } else if (SK_Scalar1 == w) { |
719 this->quadTo(x1, y1, x2, y2); | 703 this->quadTo(x1, y1, x2, y2); |
720 } else { | 704 } else { |
721 SkDEBUGCODE(this->validate();) | 705 SkDEBUGCODE(this->validate();) |
722 | 706 |
723 this->injectMoveToIfNeeded(); | 707 this->injectMoveToIfNeeded(); |
724 | 708 |
725 SkPathRef::Editor ed(&fPathRef); | 709 SkPathRef::Editor ed(&fPathRef); |
726 SkPoint* pts = ed.growForConic(w); | 710 SkPoint* pts = ed.growForVerb(kConic_Verb, w); |
727 pts[0].set(x1, y1); | 711 pts[0].set(x1, y1); |
728 pts[1].set(x2, y2); | 712 pts[1].set(x2, y2); |
729 fSegmentMask |= kConic_SegmentMask; | |
730 | 713 |
731 DIRTY_AFTER_EDIT; | 714 DIRTY_AFTER_EDIT; |
732 } | 715 } |
733 } | 716 } |
734 | 717 |
735 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, | 718 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2, |
736 SkScalar w) { | 719 SkScalar w) { |
737 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 720 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
738 SkPoint pt; | 721 SkPoint pt; |
739 this->getLastPt(&pt); | 722 this->getLastPt(&pt); |
740 this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w); | 723 this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w); |
741 } | 724 } |
742 | 725 |
743 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 726 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
744 SkScalar x3, SkScalar y3) { | 727 SkScalar x3, SkScalar y3) { |
745 SkDEBUGCODE(this->validate();) | 728 SkDEBUGCODE(this->validate();) |
746 | 729 |
747 this->injectMoveToIfNeeded(); | 730 this->injectMoveToIfNeeded(); |
748 | 731 |
749 SkPathRef::Editor ed(&fPathRef); | 732 SkPathRef::Editor ed(&fPathRef); |
750 SkPoint* pts = ed.growForVerb(kCubic_Verb); | 733 SkPoint* pts = ed.growForVerb(kCubic_Verb); |
751 pts[0].set(x1, y1); | 734 pts[0].set(x1, y1); |
752 pts[1].set(x2, y2); | 735 pts[1].set(x2, y2); |
753 pts[2].set(x3, y3); | 736 pts[2].set(x3, y3); |
754 fSegmentMask |= kCubic_SegmentMask; | |
755 | 737 |
756 DIRTY_AFTER_EDIT; | 738 DIRTY_AFTER_EDIT; |
757 } | 739 } |
758 | 740 |
759 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 741 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
760 SkScalar x3, SkScalar y3) { | 742 SkScalar x3, SkScalar y3) { |
761 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). | 743 this->injectMoveToIfNeeded(); // This can change the result of this->getLas
tPt(). |
762 SkPoint pt; | 744 SkPoint pt; |
763 this->getLastPt(&pt); | 745 this->getLastPt(&pt); |
764 this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2, | 746 this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 } | 813 } |
832 this->close(); | 814 this->close(); |
833 } | 815 } |
834 | 816 |
835 void SkPath::addPoly(const SkPoint pts[], int count, bool close) { | 817 void SkPath::addPoly(const SkPoint pts[], int count, bool close) { |
836 SkDEBUGCODE(this->validate();) | 818 SkDEBUGCODE(this->validate();) |
837 if (count <= 0) { | 819 if (count <= 0) { |
838 return; | 820 return; |
839 } | 821 } |
840 | 822 |
841 SkPathRef::Editor ed(&fPathRef); | 823 fLastMoveToIndex = fPathRef->countPoints(); |
842 fLastMoveToIndex = ed.pathRef()->countPoints(); | 824 |
843 uint8_t* vb; | |
844 SkPoint* p; | |
845 // +close makes room for the extra kClose_Verb | 825 // +close makes room for the extra kClose_Verb |
846 ed.grow(count + close, count, &vb, &p); | 826 SkPathRef::Editor ed(&fPathRef, count+close, count); |
847 | 827 |
848 memcpy(p, pts, count * sizeof(SkPoint)); | 828 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); |
849 vb[~0] = kMove_Verb; | |
850 if (count > 1) { | 829 if (count > 1) { |
851 // cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to | 830 SkPoint* p = ed.growForRepeatedVerb(kLine_Verb, count - 1); |
852 // be 0, the compiler will remove the test/branch entirely. | 831 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); |
853 if ((unsigned)count >= MIN_COUNT_FOR_MEMSET_TO_BE_FAST) { | |
854 memset(vb - count, kLine_Verb, count - 1); | |
855 } else { | |
856 for (int i = 1; i < count; ++i) { | |
857 vb[~i] = kLine_Verb; | |
858 } | |
859 } | |
860 fSegmentMask |= kLine_SegmentMask; | |
861 } | 832 } |
| 833 |
862 if (close) { | 834 if (close) { |
863 vb[~count] = kClose_Verb; | 835 ed.growForVerb(kClose_Verb); |
864 } | 836 } |
865 | 837 |
866 DIRTY_AFTER_EDIT; | 838 DIRTY_AFTER_EDIT; |
867 SkDEBUGCODE(this->validate();) | 839 SkDEBUGCODE(this->validate();) |
868 } | 840 } |
869 | 841 |
870 #include "SkGeometry.h" | 842 #include "SkGeometry.h" |
871 | 843 |
872 static int build_arc_points(const SkRect& oval, SkScalar startAngle, | 844 static int build_arc_points(const SkRect& oval, SkScalar startAngle, |
873 SkScalar sweepAngle, | 845 SkScalar sweepAngle, |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1336 const SkScalar kFullCircleAngle = SkIntToScalar(360); | 1308 const SkScalar kFullCircleAngle = SkIntToScalar(360); |
1337 | 1309 |
1338 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { | 1310 if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { |
1339 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); | 1311 this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); |
1340 return; | 1312 return; |
1341 } | 1313 } |
1342 | 1314 |
1343 SkPoint pts[kSkBuildQuadArcStorage]; | 1315 SkPoint pts[kSkBuildQuadArcStorage]; |
1344 int count = build_arc_points(oval, startAngle, sweepAngle, pts); | 1316 int count = build_arc_points(oval, startAngle, sweepAngle, pts); |
1345 | 1317 |
1346 this->incReserve(count); | 1318 SkDEBUGCODE(this->validate();) |
1347 this->moveTo(pts[0]); | 1319 SkASSERT(count & 1); |
1348 for (int i = 1; i < count; i += 2) { | 1320 |
1349 this->quadTo(pts[i], pts[i+1]); | 1321 fLastMoveToIndex = fPathRef->countPoints(); |
| 1322 |
| 1323 SkPathRef::Editor ed(&fPathRef, 1+(count-1)/2, count); |
| 1324 |
| 1325 ed.growForVerb(kMove_Verb)->set(pts[0].fX, pts[0].fY); |
| 1326 if (count > 1) { |
| 1327 SkPoint* p = ed.growForRepeatedVerb(kQuad_Verb, (count-1)/2); |
| 1328 memcpy(p, &pts[1], (count-1) * sizeof(SkPoint)); |
1350 } | 1329 } |
| 1330 |
| 1331 DIRTY_AFTER_EDIT; |
| 1332 SkDEBUGCODE(this->validate();) |
1351 } | 1333 } |
1352 | 1334 |
1353 /* | 1335 /* |
1354 Need to handle the case when the angle is sharp, and our computed end-points | 1336 Need to handle the case when the angle is sharp, and our computed end-points |
1355 for the arc go behind pt1 and/or p2... | 1337 for the arc go behind pt1 and/or p2... |
1356 */ | 1338 */ |
1357 void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, | 1339 void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, |
1358 SkScalar radius) { | 1340 SkScalar radius) { |
1359 SkVector before, after; | 1341 SkVector before, after; |
1360 | 1342 |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1664 | 1646 |
1665 dst->swap(tmp); | 1647 dst->swap(tmp); |
1666 SkPathRef::Editor ed(&dst->fPathRef); | 1648 SkPathRef::Editor ed(&dst->fPathRef); |
1667 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); | 1649 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); |
1668 dst->fDirection = kUnknown_Direction; | 1650 dst->fDirection = kUnknown_Direction; |
1669 } else { | 1651 } else { |
1670 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix
); | 1652 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix
); |
1671 | 1653 |
1672 if (this != dst) { | 1654 if (this != dst) { |
1673 dst->fFillType = fFillType; | 1655 dst->fFillType = fFillType; |
1674 dst->fSegmentMask = fSegmentMask; | |
1675 dst->fConvexity = fConvexity; | 1656 dst->fConvexity = fConvexity; |
1676 } | 1657 } |
1677 | 1658 |
1678 if (kUnknown_Direction == fDirection) { | 1659 if (kUnknown_Direction == fDirection) { |
1679 dst->fDirection = kUnknown_Direction; | 1660 dst->fDirection = kUnknown_Direction; |
1680 } else { | 1661 } else { |
1681 SkScalar det2x2 = | 1662 SkScalar det2x2 = |
1682 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix:
:kMScaleY)) - | 1663 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix:
:kMScaleY)) - |
1683 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::
kMSkewY)); | 1664 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::
kMSkewY)); |
1684 if (det2x2 < 0) { | 1665 if (det2x2 < 0) { |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2038 | 2019 |
2039 if (NULL == storage) { | 2020 if (NULL == storage) { |
2040 const int byteCount = sizeof(int32_t) + fPathRef->writeSize(); | 2021 const int byteCount = sizeof(int32_t) + fPathRef->writeSize(); |
2041 return SkAlign4(byteCount); | 2022 return SkAlign4(byteCount); |
2042 } | 2023 } |
2043 | 2024 |
2044 SkWBuffer buffer(storage); | 2025 SkWBuffer buffer(storage); |
2045 | 2026 |
2046 int32_t packed = (fConvexity << kConvexity_SerializationShift) | | 2027 int32_t packed = (fConvexity << kConvexity_SerializationShift) | |
2047 (fFillType << kFillType_SerializationShift) | | 2028 (fFillType << kFillType_SerializationShift) | |
2048 (fSegmentMask << kSegmentMask_SerializationShift) | | |
2049 (fDirection << kDirection_SerializationShift) | 2029 (fDirection << kDirection_SerializationShift) |
2050 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O | 2030 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O |
2051 | (0x1 << kNewFormat_SerializationShift) | 2031 | (0x1 << kNewFormat_SerializationShift) |
2052 #endif | 2032 #endif |
2053 ; | 2033 ; |
2054 | 2034 |
2055 buffer.write32(packed); | 2035 buffer.write32(packed); |
2056 | 2036 |
2057 fPathRef->writeToBuffer(&buffer); | 2037 fPathRef->writeToBuffer(&buffer); |
2058 | 2038 |
2059 buffer.padToAlign4(); | 2039 buffer.padToAlign4(); |
2060 return buffer.pos(); | 2040 return buffer.pos(); |
2061 } | 2041 } |
2062 | 2042 |
2063 size_t SkPath::readFromMemory(const void* storage, size_t length) { | 2043 size_t SkPath::readFromMemory(const void* storage, size_t length) { |
2064 SkRBufferWithSizeCheck buffer(storage, length); | 2044 SkRBufferWithSizeCheck buffer(storage, length); |
2065 | 2045 |
2066 int32_t packed; | 2046 int32_t packed; |
2067 if (!buffer.readS32(&packed)) { | 2047 if (!buffer.readS32(&packed)) { |
2068 return 0; | 2048 return 0; |
2069 } | 2049 } |
2070 | 2050 |
2071 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; | 2051 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; |
2072 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; | 2052 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; |
2073 fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF; | |
2074 fDirection = (packed >> kDirection_SerializationShift) & 0x3; | 2053 fDirection = (packed >> kDirection_SerializationShift) & 0x3; |
2075 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O | 2054 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O |
2076 bool newFormat = (packed >> kNewFormat_SerializationShift) & 1; | 2055 bool newFormat = (packed >> kNewFormat_SerializationShift) & 1; |
2077 #endif | 2056 #endif |
2078 | 2057 |
2079 SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer | 2058 SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer |
2080 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O | 2059 #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V16_AND_ALL_OTHER_INSTANCES_TO
O |
2081 , newFormat, packed | 2060 , newFormat, packed |
2082 #endif | 2061 #endif |
2083 ); | 2062 ); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2194 } else { | 2173 } else { |
2195 if (bounds.isEmpty()) { | 2174 if (bounds.isEmpty()) { |
2196 SkASSERT(fBounds.isEmpty()); | 2175 SkASSERT(fBounds.isEmpty()); |
2197 } else { | 2176 } else { |
2198 if (!fBounds.isEmpty()) { | 2177 if (!fBounds.isEmpty()) { |
2199 SkASSERT(fBounds.contains(bounds)); | 2178 SkASSERT(fBounds.contains(bounds)); |
2200 } | 2179 } |
2201 } | 2180 } |
2202 } | 2181 } |
2203 } | 2182 } |
2204 | |
2205 uint32_t mask = 0; | |
2206 const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbs()
; | |
2207 for (int i = 0; i < fPathRef->countVerbs(); i++) { | |
2208 switch (verbs[~i]) { | |
2209 case kLine_Verb: | |
2210 mask |= kLine_SegmentMask; | |
2211 break; | |
2212 case kQuad_Verb: | |
2213 mask |= kQuad_SegmentMask; | |
2214 break; | |
2215 case kConic_Verb: | |
2216 mask |= kConic_SegmentMask; | |
2217 break; | |
2218 case kCubic_Verb: | |
2219 mask |= kCubic_SegmentMask; | |
2220 case kMove_Verb: // these verbs aren't included in the segment mask
. | |
2221 case kClose_Verb: | |
2222 break; | |
2223 case kDone_Verb: | |
2224 SkDEBUGFAIL("Done verb shouldn't be recorded."); | |
2225 break; | |
2226 default: | |
2227 SkDEBUGFAIL("Unknown Verb"); | |
2228 break; | |
2229 } | |
2230 } | |
2231 SkASSERT(mask == fSegmentMask); | |
2232 #endif // SK_DEBUG_PATH | 2183 #endif // SK_DEBUG_PATH |
2233 } | 2184 } |
2234 #endif // SK_DEBUG | 2185 #endif // SK_DEBUG |
2235 | 2186 |
2236 /////////////////////////////////////////////////////////////////////////////// | 2187 /////////////////////////////////////////////////////////////////////////////// |
2237 | 2188 |
2238 static int sign(SkScalar x) { return x < 0; } | 2189 static int sign(SkScalar x) { return x < 0; } |
2239 #define kValueNeverReturnedBySign 2 | 2190 #define kValueNeverReturnedBySign 2 |
2240 | 2191 |
2241 static bool AlmostEqual(SkScalar compA, SkScalar compB) { | 2192 static bool AlmostEqual(SkScalar compA, SkScalar compB) { |
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2902 switch (this->getFillType()) { | 2853 switch (this->getFillType()) { |
2903 case SkPath::kEvenOdd_FillType: | 2854 case SkPath::kEvenOdd_FillType: |
2904 case SkPath::kInverseEvenOdd_FillType: | 2855 case SkPath::kInverseEvenOdd_FillType: |
2905 w &= 1; | 2856 w &= 1; |
2906 break; | 2857 break; |
2907 default: | 2858 default: |
2908 break; | 2859 break; |
2909 } | 2860 } |
2910 return SkToBool(w); | 2861 return SkToBool(w); |
2911 } | 2862 } |
OLD | NEW |