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

Side by Side Diff: src/core/SkPath.cpp

Issue 1176953002: move SkPath direction-as-computed into SkPathPriv (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 6 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
OLDNEW
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"
11 #include "SkMath.h" 11 #include "SkMath.h"
12 #include "SkPath.h" 12 #include "SkPathPriv.h"
13 #include "SkPathRef.h" 13 #include "SkPathRef.h"
14 #include "SkRRect.h" 14 #include "SkRRect.h"
15 #include "SkThread.h" 15 #include "SkThread.h"
16 16
17 //////////////////////////////////////////////////////////////////////////// 17 ////////////////////////////////////////////////////////////////////////////
18 18
19 /** 19 /**
20 * Path.bounds is defined to be the bounds of all the control points. 20 * Path.bounds is defined to be the bounds of all the control points.
21 * If we called bounds.join(r) we would skip r if r was empty, which breaks 21 * If we called bounds.join(r) we would skip r if r was empty, which breaks
22 * our promise. Hence we have a custom joiner that doesn't look at emptiness 22 * our promise. Hence we have a custom joiner that doesn't look at emptiness
23 */ 23 */
24 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) { 24 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) {
25 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft); 25 dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft);
26 dst->fTop = SkMinScalar(dst->fTop, src.fTop); 26 dst->fTop = SkMinScalar(dst->fTop, src.fTop);
27 dst->fRight = SkMaxScalar(dst->fRight, src.fRight); 27 dst->fRight = SkMaxScalar(dst->fRight, src.fRight);
28 dst->fBottom = SkMaxScalar(dst->fBottom, src.fBottom); 28 dst->fBottom = SkMaxScalar(dst->fBottom, src.fBottom);
29 } 29 }
30 30
31 static bool is_degenerate(const SkPath& path) { 31 static bool is_degenerate(const SkPath& path) {
32 SkPath::Iter iter(path, false); 32 SkPath::Iter iter(path, false);
33 SkPoint pts[4]; 33 SkPoint pts[4];
34 return SkPath::kDone_Verb == iter.next(pts); 34 return SkPath::kDone_Verb == iter.next(pts);
35 } 35 }
36 36
37 class SkAutoDisableDirectionCheck { 37 class SkAutoDisableDirectionCheck {
38 public: 38 public:
39 SkAutoDisableDirectionCheck(SkPath* path) : fPath(path) { 39 SkAutoDisableDirectionCheck(SkPath* path) : fPath(path) {
40 fSaved = static_cast<SkPath::Direction>(fPath->fDirection); 40 fSaved = static_cast<SkPathPriv::FirstDirection>(fPath->fFirstDirection) ;
41 } 41 }
42 42
43 ~SkAutoDisableDirectionCheck() { 43 ~SkAutoDisableDirectionCheck() {
44 fPath->fDirection = fSaved; 44 fPath->fFirstDirection = fSaved;
45 } 45 }
46 46
47 private: 47 private:
48 SkPath* fPath; 48 SkPath* fPath;
49 SkPath::Direction fSaved; 49 SkPathPriv::FirstDirection fSaved;
50 }; 50 };
51 #define SkAutoDisableDirectionCheck(...) SK_REQUIRE_LOCAL_VAR(SkAutoDisableDirec tionCheck) 51 #define SkAutoDisableDirectionCheck(...) SK_REQUIRE_LOCAL_VAR(SkAutoDisableDirec tionCheck)
52 52
53 /* This guy's constructor/destructor bracket a path editing operation. It is 53 /* This guy's constructor/destructor bracket a path editing operation. It is
54 used when we know the bounds of the amount we are going to add to the path 54 used when we know the bounds of the amount we are going to add to the path
55 (usually a new contour, but not required). 55 (usually a new contour, but not required).
56 56
57 It captures some state about the path up front (i.e. if it already has a 57 It captures some state about the path up front (i.e. if it already has a
58 cached bounds), and then if it can, it updates the cache bounds explicitly, 58 cached bounds), and then if it can, it updates the cache bounds explicitly,
59 avoiding the need to revisit all of the points in getBounds(). 59 avoiding the need to revisit all of the points in getBounds().
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 : fPathRef(SkPathRef::CreateEmpty()) { 128 : fPathRef(SkPathRef::CreateEmpty()) {
129 this->resetFields(); 129 this->resetFields();
130 fIsVolatile = false; 130 fIsVolatile = false;
131 } 131 }
132 132
133 void SkPath::resetFields() { 133 void SkPath::resetFields() {
134 //fPathRef is assumed to have been emptied by the caller. 134 //fPathRef is assumed to have been emptied by the caller.
135 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; 135 fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
136 fFillType = kWinding_FillType; 136 fFillType = kWinding_FillType;
137 fConvexity = kUnknown_Convexity; 137 fConvexity = kUnknown_Convexity;
138 fDirection = kUnknown_Direction; 138 fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
139 139
140 // 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
141 // 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.
142 } 142 }
143 143
144 SkPath::SkPath(const SkPath& that) 144 SkPath::SkPath(const SkPath& that)
145 : fPathRef(SkRef(that.fPathRef.get())) { 145 : fPathRef(SkRef(that.fPathRef.get())) {
146 this->copyFields(that); 146 this->copyFields(that);
147 SkDEBUGCODE(that.validate();) 147 SkDEBUGCODE(that.validate();)
148 } 148 }
(...skipping 11 matching lines...) Expand all
160 } 160 }
161 SkDEBUGCODE(this->validate();) 161 SkDEBUGCODE(this->validate();)
162 return *this; 162 return *this;
163 } 163 }
164 164
165 void SkPath::copyFields(const SkPath& that) { 165 void SkPath::copyFields(const SkPath& that) {
166 //fPathRef is assumed to have been set by the caller. 166 //fPathRef is assumed to have been set by the caller.
167 fLastMoveToIndex = that.fLastMoveToIndex; 167 fLastMoveToIndex = that.fLastMoveToIndex;
168 fFillType = that.fFillType; 168 fFillType = that.fFillType;
169 fConvexity = that.fConvexity; 169 fConvexity = that.fConvexity;
170 fDirection = that.fDirection; 170 fFirstDirection = that.fFirstDirection;
171 fIsVolatile = that.fIsVolatile; 171 fIsVolatile = that.fIsVolatile;
172 } 172 }
173 173
174 bool operator==(const SkPath& a, const SkPath& b) { 174 bool operator==(const SkPath& a, const SkPath& b) {
175 // note: don't need to look at isConvex or bounds, since just comparing the 175 // note: don't need to look at isConvex or bounds, since just comparing the
176 // raw data is sufficient. 176 // raw data is sufficient.
177 return &a == &b || 177 return &a == &b ||
178 (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get()); 178 (a.fFillType == b.fFillType && *a.fPathRef.get() == *b.fPathRef.get());
179 } 179 }
180 180
181 void SkPath::swap(SkPath& that) { 181 void SkPath::swap(SkPath& that) {
182 if (this != &that) { 182 if (this != &that) {
183 fPathRef.swap(&that.fPathRef); 183 fPathRef.swap(&that.fPathRef);
184 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex); 184 SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
185 SkTSwap<uint8_t>(fFillType, that.fFillType); 185 SkTSwap<uint8_t>(fFillType, that.fFillType);
186 SkTSwap<uint8_t>(fConvexity, that.fConvexity); 186 SkTSwap<uint8_t>(fConvexity, that.fConvexity);
187 SkTSwap<uint8_t>(fDirection, that.fDirection); 187 SkTSwap<uint8_t>(fFirstDirection, that.fFirstDirection);
188 SkTSwap<SkBool8>(fIsVolatile, that.fIsVolatile); 188 SkTSwap<SkBool8>(fIsVolatile, that.fIsVolatile);
189 } 189 }
190 } 190 }
191 191
192 static inline bool check_edge_against_rect(const SkPoint& p0, 192 static inline bool check_edge_against_rect(const SkPoint& p0,
193 const SkPoint& p1, 193 const SkPoint& p1,
194 const SkRect& rect, 194 const SkRect& rect,
195 SkPath::Direction dir) { 195 SkPathPriv::FirstDirection dir) {
196 const SkPoint* edgeBegin; 196 const SkPoint* edgeBegin;
197 SkVector v; 197 SkVector v;
198 if (SkPath::kCW_Direction == dir) { 198 if (SkPathPriv::kCW_FirstDirection == dir) {
199 v = p1 - p0; 199 v = p1 - p0;
200 edgeBegin = &p0; 200 edgeBegin = &p0;
201 } else { 201 } else {
202 v = p0 - p1; 202 v = p0 - p1;
203 edgeBegin = &p1; 203 edgeBegin = &p1;
204 } 204 }
205 if (v.fX || v.fY) { 205 if (v.fX || v.fY) {
206 // check the cross product of v with the vec from edgeBegin to each rect corner 206 // check the cross product of v with the vec from edgeBegin to each rect corner
207 SkScalar yL = SkScalarMul(v.fY, rect.fLeft - edgeBegin->fX); 207 SkScalar yL = SkScalarMul(v.fY, rect.fLeft - edgeBegin->fX);
208 SkScalar xT = SkScalarMul(v.fX, rect.fTop - edgeBegin->fY); 208 SkScalar xT = SkScalarMul(v.fX, rect.fTop - edgeBegin->fY);
209 SkScalar yR = SkScalarMul(v.fY, rect.fRight - edgeBegin->fX); 209 SkScalar yR = SkScalarMul(v.fY, rect.fRight - edgeBegin->fX);
210 SkScalar xB = SkScalarMul(v.fX, rect.fBottom - edgeBegin->fY); 210 SkScalar xB = SkScalarMul(v.fX, rect.fBottom - edgeBegin->fY);
211 if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) { 211 if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
212 return false; 212 return false;
213 } 213 }
214 } 214 }
215 return true; 215 return true;
216 } 216 }
217 217
218 bool SkPath::conservativelyContainsRect(const SkRect& rect) const { 218 bool SkPath::conservativelyContainsRect(const SkRect& rect) const {
219 // This only handles non-degenerate convex paths currently. 219 // This only handles non-degenerate convex paths currently.
220 if (kConvex_Convexity != this->getConvexity()) { 220 if (kConvex_Convexity != this->getConvexity()) {
221 return false; 221 return false;
222 } 222 }
223 223
224 Direction direction; 224 SkPathPriv::FirstDirection direction;
225 if (!this->cheapComputeDirection(&direction)) { 225 if (!SkPathPriv::CheapComputeFirstDirection(*this, &direction)) {
226 return false; 226 return false;
227 } 227 }
228 228
229 SkPoint firstPt; 229 SkPoint firstPt;
230 SkPoint prevPt; 230 SkPoint prevPt;
231 RawIter iter(*this); 231 RawIter iter(*this);
232 SkPath::Verb verb; 232 SkPath::Verb verb;
233 SkPoint pts[4]; 233 SkPoint pts[4];
234 SkDEBUGCODE(int moveCnt = 0;) 234 SkDEBUGCODE(int moveCnt = 0;)
235 SkDEBUGCODE(int segmentCount = 0;) 235 SkDEBUGCODE(int segmentCount = 0;)
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 655
656 void SkPath::setConvexity(Convexity c) { 656 void SkPath::setConvexity(Convexity c) {
657 if (fConvexity != c) { 657 if (fConvexity != c) {
658 fConvexity = c; 658 fConvexity = c;
659 } 659 }
660 } 660 }
661 661
662 ////////////////////////////////////////////////////////////////////////////// 662 //////////////////////////////////////////////////////////////////////////////
663 // Construction methods 663 // Construction methods
664 664
665 #define DIRTY_AFTER_EDIT \ 665 #define DIRTY_AFTER_EDIT \
666 do { \ 666 do { \
667 fConvexity = kUnknown_Convexity; \ 667 fConvexity = kUnknown_Convexity; \
668 fDirection = kUnknown_Direction; \ 668 fFirstDirection = SkPathPriv::kUnknown_FirstDirection; \
669 } while (0) 669 } while (0)
670 670
671 void SkPath::incReserve(U16CPU inc) { 671 void SkPath::incReserve(U16CPU inc) {
672 SkDEBUGCODE(this->validate();) 672 SkDEBUGCODE(this->validate();)
673 SkPathRef::Editor(&fPathRef, inc, inc); 673 SkPathRef::Editor(&fPathRef, inc, inc);
674 SkDEBUGCODE(this->validate();) 674 SkDEBUGCODE(this->validate();)
675 } 675 }
676 676
677 void SkPath::moveTo(SkScalar x, SkScalar y) { 677 void SkPath::moveTo(SkScalar x, SkScalar y) {
678 SkDEBUGCODE(this->validate();) 678 SkDEBUGCODE(this->validate();)
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir); 841 SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir);
842 } 842 }
843 843
844 void SkPath::addRect(const SkRect& rect, Direction dir) { 844 void SkPath::addRect(const SkRect& rect, Direction dir) {
845 this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir); 845 this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir);
846 } 846 }
847 847
848 void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right, 848 void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
849 SkScalar bottom, Direction dir) { 849 SkScalar bottom, Direction dir) {
850 assert_known_direction(dir); 850 assert_known_direction(dir);
851 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; 851 fFirstDirection = this->hasOnlyMoveTos() ?
852 (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnknown_F irstDirection;
852 SkAutoDisableDirectionCheck addc(this); 853 SkAutoDisableDirectionCheck addc(this);
853 854
854 SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom); 855 SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom);
855 856
856 this->incReserve(5); 857 this->incReserve(5);
857 858
858 this->moveTo(left, top); 859 this->moveTo(left, top);
859 if (dir == kCCW_Direction) { 860 if (dir == kCCW_Direction) {
860 this->lineTo(left, bottom); 861 this->lineTo(left, bottom);
861 this->lineTo(right, bottom); 862 this->lineTo(right, bottom);
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
981 return; 982 return;
982 } 983 }
983 984
984 const SkRect& bounds = rrect.getBounds(); 985 const SkRect& bounds = rrect.getBounds();
985 986
986 if (rrect.isRect()) { 987 if (rrect.isRect()) {
987 this->addRect(bounds, dir); 988 this->addRect(bounds, dir);
988 } else if (rrect.isOval()) { 989 } else if (rrect.isOval()) {
989 this->addOval(bounds, dir); 990 this->addOval(bounds, dir);
990 } else { 991 } else {
991 fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction; 992 fFirstDirection = this->hasOnlyMoveTos() ?
993 (SkPathPriv::FirstDirection)dir : SkPathPriv::kUnkno wn_FirstDirection;
992 994
993 SkAutoPathBoundsUpdate apbu(this, bounds); 995 SkAutoPathBoundsUpdate apbu(this, bounds);
994 SkAutoDisableDirectionCheck addc(this); 996 SkAutoDisableDirectionCheck addc(this);
995 997
996 const SkScalar L = bounds.fLeft; 998 const SkScalar L = bounds.fLeft;
997 const SkScalar T = bounds.fTop; 999 const SkScalar T = bounds.fTop;
998 const SkScalar R = bounds.fRight; 1000 const SkScalar R = bounds.fRight;
999 const SkScalar B = bounds.fBottom; 1001 const SkScalar B = bounds.fBottom;
1000 const SkScalar W = SK_ScalarRoot2Over2; 1002 const SkScalar W = SK_ScalarRoot2Over2;
1001 1003
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 assert_known_direction(dir); 1072 assert_known_direction(dir);
1071 1073
1072 /* If addOval() is called after previous moveTo(), 1074 /* If addOval() is called after previous moveTo(),
1073 this path is still marked as an oval. This is used to 1075 this path is still marked as an oval. This is used to
1074 fit into WebKit's calling sequences. 1076 fit into WebKit's calling sequences.
1075 We can't simply check isEmpty() in this case, as additional 1077 We can't simply check isEmpty() in this case, as additional
1076 moveTo() would mark the path non empty. 1078 moveTo() would mark the path non empty.
1077 */ 1079 */
1078 bool isOval = hasOnlyMoveTos(); 1080 bool isOval = hasOnlyMoveTos();
1079 if (isOval) { 1081 if (isOval) {
1080 fDirection = dir; 1082 fFirstDirection = (SkPathPriv::FirstDirection)dir;
1081 } else { 1083 } else {
1082 fDirection = kUnknown_Direction; 1084 fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
1083 } 1085 }
1084 1086
1085 SkAutoDisableDirectionCheck addc(this); 1087 SkAutoDisableDirectionCheck addc(this);
1086 1088
1087 SkAutoPathBoundsUpdate apbu(this, oval); 1089 SkAutoPathBoundsUpdate apbu(this, oval);
1088 1090
1089 const SkScalar L = oval.fLeft; 1091 const SkScalar L = oval.fLeft;
1090 const SkScalar T = oval.fTop; 1092 const SkScalar T = oval.fTop;
1091 const SkScalar R = oval.fRight; 1093 const SkScalar R = oval.fRight;
1092 const SkScalar B = oval.fBottom; 1094 const SkScalar B = oval.fBottom;
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
1470 break; 1472 break;
1471 default: 1473 default:
1472 SkDEBUGFAIL("unknown verb"); 1474 SkDEBUGFAIL("unknown verb");
1473 break; 1475 break;
1474 } 1476 }
1475 } 1477 }
1476 1478
1477 dst->swap(tmp); 1479 dst->swap(tmp);
1478 SkPathRef::Editor ed(&dst->fPathRef); 1480 SkPathRef::Editor ed(&dst->fPathRef);
1479 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints()); 1481 matrix.mapPoints(ed.points(), ed.pathRef()->countPoints());
1480 dst->fDirection = kUnknown_Direction; 1482 dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
1481 } else { 1483 } else {
1482 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix ); 1484 SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix );
1483 1485
1484 if (this != dst) { 1486 if (this != dst) {
1485 dst->fFillType = fFillType; 1487 dst->fFillType = fFillType;
1486 dst->fConvexity = fConvexity; 1488 dst->fConvexity = fConvexity;
1487 dst->fIsVolatile = fIsVolatile; 1489 dst->fIsVolatile = fIsVolatile;
1488 } 1490 }
1489 1491
1490 if (kUnknown_Direction == fDirection) { 1492 if (SkPathPriv::kUnknown_FirstDirection == fFirstDirection) {
1491 dst->fDirection = kUnknown_Direction; 1493 dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
1492 } else { 1494 } else {
1493 SkScalar det2x2 = 1495 SkScalar det2x2 =
1494 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix: :kMScaleY)) - 1496 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix: :kMScaleY)) -
1495 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix:: kMSkewY)); 1497 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix:: kMSkewY));
1496 if (det2x2 < 0) { 1498 if (det2x2 < 0) {
1497 dst->fDirection = SkPath::OppositeDirection(static_cast<Directio n>(fDirection)); 1499 dst->fFirstDirection = SkPathPriv::OppositeFirstDirection((SkPat hPriv::FirstDirection)fFirstDirection);
1498 } else if (det2x2 > 0) { 1500 } else if (det2x2 > 0) {
1499 dst->fDirection = fDirection; 1501 dst->fFirstDirection = fFirstDirection;
1500 } else { 1502 } else {
1501 dst->fConvexity = kUnknown_Convexity; 1503 dst->fConvexity = kUnknown_Convexity;
1502 dst->fDirection = kUnknown_Direction; 1504 dst->fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
1503 } 1505 }
1504 } 1506 }
1505 1507
1506 SkDEBUGCODE(dst->validate();) 1508 SkDEBUGCODE(dst->validate();)
1507 } 1509 }
1508 } 1510 }
1509 1511
1510 /////////////////////////////////////////////////////////////////////////////// 1512 ///////////////////////////////////////////////////////////////////////////////
1511 /////////////////////////////////////////////////////////////////////////////// 1513 ///////////////////////////////////////////////////////////////////////////////
1512 1514
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 1853
1852 if (NULL == storage) { 1854 if (NULL == storage) {
1853 const int byteCount = sizeof(int32_t) + fPathRef->writeSize(); 1855 const int byteCount = sizeof(int32_t) + fPathRef->writeSize();
1854 return SkAlign4(byteCount); 1856 return SkAlign4(byteCount);
1855 } 1857 }
1856 1858
1857 SkWBuffer buffer(storage); 1859 SkWBuffer buffer(storage);
1858 1860
1859 int32_t packed = (fConvexity << kConvexity_SerializationShift) | 1861 int32_t packed = (fConvexity << kConvexity_SerializationShift) |
1860 (fFillType << kFillType_SerializationShift) | 1862 (fFillType << kFillType_SerializationShift) |
1861 (fDirection << kDirection_SerializationShift) | 1863 (fFirstDirection << kDirection_SerializationShift) |
1862 (fIsVolatile << kIsVolatile_SerializationShift); 1864 (fIsVolatile << kIsVolatile_SerializationShift);
1863 1865
1864 buffer.write32(packed); 1866 buffer.write32(packed);
1865 1867
1866 fPathRef->writeToBuffer(&buffer); 1868 fPathRef->writeToBuffer(&buffer);
1867 1869
1868 buffer.padToAlign4(); 1870 buffer.padToAlign4();
1869 return buffer.pos(); 1871 return buffer.pos();
1870 } 1872 }
1871 1873
1872 size_t SkPath::readFromMemory(const void* storage, size_t length) { 1874 size_t SkPath::readFromMemory(const void* storage, size_t length) {
1873 SkRBufferWithSizeCheck buffer(storage, length); 1875 SkRBufferWithSizeCheck buffer(storage, length);
1874 1876
1875 int32_t packed; 1877 int32_t packed;
1876 if (!buffer.readS32(&packed)) { 1878 if (!buffer.readS32(&packed)) {
1877 return 0; 1879 return 0;
1878 } 1880 }
1879 1881
1880 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF; 1882 fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
1881 fFillType = (packed >> kFillType_SerializationShift) & 0xFF; 1883 fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
1882 fDirection = (packed >> kDirection_SerializationShift) & 0x3; 1884 fFirstDirection = (packed >> kDirection_SerializationShift) & 0x3;
1883 fIsVolatile = (packed >> kIsVolatile_SerializationShift) & 0x1; 1885 fIsVolatile = (packed >> kIsVolatile_SerializationShift) & 0x1;
1884 SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer); 1886 SkPathRef* pathRef = SkPathRef::CreateFromBuffer(&buffer);
1885 1887
1886 size_t sizeRead = 0; 1888 size_t sizeRead = 0;
1887 if (buffer.isValid()) { 1889 if (buffer.isValid()) {
1888 fPathRef.reset(pathRef); 1890 fPathRef.reset(pathRef);
1889 SkDEBUGCODE(this->validate();) 1891 SkDEBUGCODE(this->validate();)
1890 buffer.skipToAlign4(); 1892 buffer.skipToAlign4();
1891 sizeRead = buffer.pos(); 1893 sizeRead = buffer.pos();
1892 } else if (pathRef) { 1894 } else if (pathRef) {
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 static bool approximately_zero_when_compared_to(double x, double y) { 2056 static bool approximately_zero_when_compared_to(double x, double y) {
2055 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON); 2057 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
2056 } 2058 }
2057 2059
2058 2060
2059 // only valid for a single contour 2061 // only valid for a single contour
2060 struct Convexicator { 2062 struct Convexicator {
2061 Convexicator() 2063 Convexicator()
2062 : fPtCount(0) 2064 : fPtCount(0)
2063 , fConvexity(SkPath::kConvex_Convexity) 2065 , fConvexity(SkPath::kConvex_Convexity)
2064 , fDirection(SkPath::kUnknown_Direction) 2066 , fFirstDirection(SkPathPriv::kUnknown_FirstDirection)
2065 , fIsFinite(true) 2067 , fIsFinite(true)
2066 , fIsCurve(false) { 2068 , fIsCurve(false) {
2067 fExpectedDir = kInvalid_DirChange; 2069 fExpectedDir = kInvalid_DirChange;
2068 // warnings 2070 // warnings
2069 fLastPt.set(0, 0); 2071 fLastPt.set(0, 0);
2070 fCurrPt.set(0, 0); 2072 fCurrPt.set(0, 0);
2071 fLastVec.set(0, 0); 2073 fLastVec.set(0, 0);
2072 fFirstVec.set(0, 0); 2074 fFirstVec.set(0, 0);
2073 2075
2074 fDx = fDy = 0; 2076 fDx = fDy = 0;
2075 fSx = fSy = kValueNeverReturnedBySign; 2077 fSx = fSy = kValueNeverReturnedBySign;
2076 } 2078 }
2077 2079
2078 SkPath::Convexity getConvexity() const { return fConvexity; } 2080 SkPath::Convexity getConvexity() const { return fConvexity; }
2079 2081
2080 /** The direction returned is only valid if the path is determined convex */ 2082 /** The direction returned is only valid if the path is determined convex */
2081 SkPath::Direction getDirection() const { return fDirection; } 2083 SkPathPriv::FirstDirection getFirstDirection() const { return fFirstDirectio n; }
2082 2084
2083 void addPt(const SkPoint& pt) { 2085 void addPt(const SkPoint& pt) {
2084 if (SkPath::kConcave_Convexity == fConvexity || !fIsFinite) { 2086 if (SkPath::kConcave_Convexity == fConvexity || !fIsFinite) {
2085 return; 2087 return;
2086 } 2088 }
2087 2089
2088 if (0 == fPtCount) { 2090 if (0 == fPtCount) {
2089 fCurrPt = pt; 2091 fCurrPt = pt;
2090 ++fPtCount; 2092 ++fPtCount;
2091 } else { 2093 } else {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2172 2174
2173 private: 2175 private:
2174 void addVec(const SkVector& vec) { 2176 void addVec(const SkVector& vec) {
2175 SkASSERT(vec.fX || vec.fY); 2177 SkASSERT(vec.fX || vec.fY);
2176 DirChange dir = this->directionChange(vec); 2178 DirChange dir = this->directionChange(vec);
2177 switch (dir) { 2179 switch (dir) {
2178 case kLeft_DirChange: // fall through 2180 case kLeft_DirChange: // fall through
2179 case kRight_DirChange: 2181 case kRight_DirChange:
2180 if (kInvalid_DirChange == fExpectedDir) { 2182 if (kInvalid_DirChange == fExpectedDir) {
2181 fExpectedDir = dir; 2183 fExpectedDir = dir;
2182 fDirection = (kRight_DirChange == dir) ? SkPath::kCW_Directi on 2184 fFirstDirection = (kRight_DirChange == dir) ? SkPathPriv::kC W_FirstDirection
2183 : SkPath::kCCW_Direct ion; 2185 : SkPathPriv::kC CW_FirstDirection;
2184 } else if (dir != fExpectedDir) { 2186 } else if (dir != fExpectedDir) {
2185 fConvexity = SkPath::kConcave_Convexity; 2187 fConvexity = SkPath::kConcave_Convexity;
2186 fDirection = SkPath::kUnknown_Direction; 2188 fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
2187 } 2189 }
2188 fLastVec = vec; 2190 fLastVec = vec;
2189 break; 2191 break;
2190 case kStraight_DirChange: 2192 case kStraight_DirChange:
2191 break; 2193 break;
2192 case kBackwards_DirChange: 2194 case kBackwards_DirChange:
2193 if (fIsCurve) { 2195 if (fIsCurve) {
2194 fConvexity = SkPath::kConcave_Convexity; 2196 fConvexity = SkPath::kConcave_Convexity;
2195 fDirection = SkPath::kUnknown_Direction; 2197 fFirstDirection = SkPathPriv::kUnknown_FirstDirection;
2196 } 2198 }
2197 fLastVec = vec; 2199 fLastVec = vec;
2198 break; 2200 break;
2199 case kInvalid_DirChange: 2201 case kInvalid_DirChange:
2200 SkFAIL("Use of invalid direction change flag"); 2202 SkFAIL("Use of invalid direction change flag");
2201 break; 2203 break;
2202 } 2204 }
2203 } 2205 }
2204 2206
2205 SkPoint fPriorPt; 2207 SkPoint fPriorPt;
2206 SkPoint fLastPt; 2208 SkPoint fLastPt;
2207 SkPoint fCurrPt; 2209 SkPoint fCurrPt;
2208 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product 2210 // fLastVec does not necessarily start at fLastPt. We only advance it when t he cross product
2209 // value with the current vec is deemed to be of a significant value. 2211 // value with the current vec is deemed to be of a significant value.
2210 SkVector fLastVec, fFirstVec; 2212 SkVector fLastVec, fFirstVec;
2211 int fPtCount; // non-degenerate points 2213 int fPtCount; // non-degenerate points
2212 DirChange fExpectedDir; 2214 DirChange fExpectedDir;
2213 SkPath::Convexity fConvexity; 2215 SkPath::Convexity fConvexity;
2214 SkPath::Direction fDirection; 2216 SkPathPriv::FirstDirection fFirstDirection;
2215 int fDx, fDy, fSx, fSy; 2217 int fDx, fDy, fSx, fSy;
2216 bool fIsFinite; 2218 bool fIsFinite;
2217 bool fIsCurve; 2219 bool fIsCurve;
2218 }; 2220 };
2219 2221
2220 SkPath::Convexity SkPath::internalGetConvexity() const { 2222 SkPath::Convexity SkPath::internalGetConvexity() const {
2221 SkASSERT(kUnknown_Convexity == fConvexity); 2223 SkASSERT(kUnknown_Convexity == fConvexity);
2222 SkPoint pts[4]; 2224 SkPoint pts[4];
2223 SkPath::Verb verb; 2225 SkPath::Verb verb;
2224 SkPath::Iter iter(*this, true); 2226 SkPath::Iter iter(*this, true);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2270 // early exit 2272 // early exit
2271 if (!state.isFinite()) { 2273 if (!state.isFinite()) {
2272 return kUnknown_Convexity; 2274 return kUnknown_Convexity;
2273 } 2275 }
2274 if (kConcave_Convexity == state.getConvexity()) { 2276 if (kConcave_Convexity == state.getConvexity()) {
2275 fConvexity = kConcave_Convexity; 2277 fConvexity = kConcave_Convexity;
2276 return kConcave_Convexity; 2278 return kConcave_Convexity;
2277 } 2279 }
2278 } 2280 }
2279 fConvexity = state.getConvexity(); 2281 fConvexity = state.getConvexity();
2280 if (kConvex_Convexity == fConvexity && kUnknown_Direction == fDirection) { 2282 if (kConvex_Convexity == fConvexity && SkPathPriv::kUnknown_FirstDirection = = fFirstDirection) {
2281 fDirection = state.getDirection(); 2283 fFirstDirection = state.getFirstDirection();
2282 } 2284 }
2283 return static_cast<Convexity>(fConvexity); 2285 return static_cast<Convexity>(fConvexity);
2284 } 2286 }
2285 2287
2286 /////////////////////////////////////////////////////////////////////////////// 2288 ///////////////////////////////////////////////////////////////////////////////
2287 2289
2288 class ContourIter { 2290 class ContourIter {
2289 public: 2291 public:
2290 ContourIter(const SkPathRef& pathRef); 2292 ContourIter(const SkPathRef& pathRef);
2291 2293
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2431 min = x; 2433 min = x;
2432 minIndex = i; 2434 minIndex = i;
2433 } else if (x > max) { 2435 } else if (x > max) {
2434 max = x; 2436 max = x;
2435 maxIndex = i; 2437 maxIndex = i;
2436 } 2438 }
2437 } 2439 }
2438 *maxIndexPtr = maxIndex; 2440 *maxIndexPtr = maxIndex;
2439 return minIndex; 2441 return minIndex;
2440 } 2442 }
2441 2443
robertphillips 2015/06/15 15:22:35 cross_to_dir ?
2442 static void crossToDir(SkScalar cross, SkPath::Direction* dir) { 2444 static void crossToDir(SkScalar cross, SkPathPriv::FirstDirection* dir) {
2443 *dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction; 2445 *dir = cross > 0 ? SkPathPriv::kCW_FirstDirection : SkPathPriv::kCCW_FirstDi rection;
2444 } 2446 }
2445 2447
2446 /* 2448 /*
2447 * We loop through all contours, and keep the computed cross-product of the 2449 * We loop through all contours, and keep the computed cross-product of the
2448 * contour that contained the global y-max. If we just look at the first 2450 * contour that contained the global y-max. If we just look at the first
2449 * contour, we may find one that is wound the opposite way (correctly) since 2451 * contour, we may find one that is wound the opposite way (correctly) since
2450 * it is the interior of a hole (e.g. 'o'). Thus we must find the contour 2452 * it is the interior of a hole (e.g. 'o'). Thus we must find the contour
2451 * that is outer most (or at least has the global y-max) before we can consider 2453 * that is outer most (or at least has the global y-max) before we can consider
2452 * its cross product. 2454 * its cross product.
2453 */ 2455 */
2454 bool SkPath::cheapComputeDirection(Direction* dir) const { 2456 bool SkPathPriv::CheapComputeFirstDirection(const SkPath& path, FirstDirection* dir) {
2455 if (kUnknown_Direction != fDirection) { 2457 if (kUnknown_FirstDirection != path.fFirstDirection) {
2456 *dir = static_cast<Direction>(fDirection); 2458 *dir = static_cast<FirstDirection>(path.fFirstDirection);
2457 return true; 2459 return true;
2458 } 2460 }
2459 2461
2460 // don't want to pay the cost for computing this if it 2462 // don't want to pay the cost for computing this if it
2461 // is unknown, so we don't call isConvex() 2463 // is unknown, so we don't call isConvex()
2462 if (kConvex_Convexity == this->getConvexityOrUnknown()) { 2464 if (SkPath::kConvex_Convexity == path.getConvexityOrUnknown()) {
2463 SkASSERT(kUnknown_Direction == fDirection); 2465 SkASSERT(kUnknown_FirstDirection == path.fFirstDirection);
2464 *dir = static_cast<Direction>(fDirection); 2466 *dir = static_cast<FirstDirection>(path.fFirstDirection);
2465 return false; 2467 return false;
2466 } 2468 }
2467 2469
2468 ContourIter iter(*fPathRef.get()); 2470 ContourIter iter(*path.fPathRef.get());
2469 2471
2470 // initialize with our logical y-min 2472 // initialize with our logical y-min
2471 SkScalar ymax = this->getBounds().fTop; 2473 SkScalar ymax = path.getBounds().fTop;
2472 SkScalar ymaxCross = 0; 2474 SkScalar ymaxCross = 0;
2473 2475
2474 for (; !iter.done(); iter.next()) { 2476 for (; !iter.done(); iter.next()) {
2475 int n = iter.count(); 2477 int n = iter.count();
2476 if (n < 3) { 2478 if (n < 3) {
2477 continue; 2479 continue;
2478 } 2480 }
2479 2481
2480 const SkPoint* pts = iter.pts(); 2482 const SkPoint* pts = iter.pts();
2481 SkScalar cross = 0; 2483 SkScalar cross = 0;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2527 } 2529 }
2528 2530
2529 if (cross) { 2531 if (cross) {
2530 // record our best guess so far 2532 // record our best guess so far
2531 ymax = pts[index].fY; 2533 ymax = pts[index].fY;
2532 ymaxCross = cross; 2534 ymaxCross = cross;
2533 } 2535 }
2534 } 2536 }
2535 if (ymaxCross) { 2537 if (ymaxCross) {
2536 crossToDir(ymaxCross, dir); 2538 crossToDir(ymaxCross, dir);
2537 fDirection = *dir; 2539 path.fFirstDirection = *dir;
2538 return true; 2540 return true;
2539 } else { 2541 } else {
2540 return false; 2542 return false;
2541 } 2543 }
2542 } 2544 }
2543 2545
2544 /////////////////////////////////////////////////////////////////////////////// 2546 ///////////////////////////////////////////////////////////////////////////////
2545 2547
2546 static SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C, 2548 static SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C,
2547 SkScalar D, SkScalar t) { 2549 SkScalar D, SkScalar t) {
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2785 switch (this->getFillType()) { 2787 switch (this->getFillType()) {
2786 case SkPath::kEvenOdd_FillType: 2788 case SkPath::kEvenOdd_FillType:
2787 case SkPath::kInverseEvenOdd_FillType: 2789 case SkPath::kInverseEvenOdd_FillType:
2788 w &= 1; 2790 w &= 1;
2789 break; 2791 break;
2790 default: 2792 default:
2791 break; 2793 break;
2792 } 2794 }
2793 return SkToBool(w); 2795 return SkToBool(w);
2794 } 2796 }
OLDNEW
« no previous file with comments | « include/core/SkPath.h ('k') | src/core/SkPathPriv.h » ('j') | src/core/SkPathPriv.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698