• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkPolyUtils.h"
9 
10 #include <limits>
11 
12 #include "SkNx.h"
13 #include "SkPointPriv.h"
14 #include "SkTArray.h"
15 #include "SkTemplates.h"
16 #include "SkTDPQueue.h"
17 #include "SkTInternalLList.h"
18 
19 //////////////////////////////////////////////////////////////////////////////////
20 // Helper data structures and functions
21 
22 struct OffsetSegment {
23     SkPoint fP0;
24     SkVector fV;
25 };
26 
27 constexpr SkScalar kCrossTolerance = SK_ScalarNearlyZero * SK_ScalarNearlyZero;
28 
29 // Computes perpDot for point p compared to segment defined by origin p0 and vector v.
30 // A positive value means the point is to the left of the segment,
31 // negative is to the right, 0 is collinear.
compute_side(const SkPoint & p0,const SkVector & v,const SkPoint & p)32 static int compute_side(const SkPoint& p0, const SkVector& v, const SkPoint& p) {
33     SkVector w = p - p0;
34     SkScalar perpDot = v.cross(w);
35     if (!SkScalarNearlyZero(perpDot, kCrossTolerance)) {
36         return ((perpDot > 0) ? 1 : -1);
37     }
38 
39     return 0;
40 }
41 
42 // Returns 1 for cw, -1 for ccw and 0 if zero signed area (either degenerate or self-intersecting)
SkGetPolygonWinding(const SkPoint * polygonVerts,int polygonSize)43 int SkGetPolygonWinding(const SkPoint* polygonVerts, int polygonSize) {
44     if (polygonSize < 3) {
45         return 0;
46     }
47 
48     // compute area and use sign to determine winding
49     SkScalar quadArea = 0;
50     SkVector v0 = polygonVerts[1] - polygonVerts[0];
51     for (int curr = 2; curr < polygonSize; ++curr) {
52         SkVector v1 = polygonVerts[curr] - polygonVerts[0];
53         quadArea += v0.cross(v1);
54         v0 = v1;
55     }
56     if (SkScalarNearlyZero(quadArea, kCrossTolerance)) {
57         return 0;
58     }
59     // 1 == ccw, -1 == cw
60     return (quadArea > 0) ? 1 : -1;
61 }
62 
63 // Compute difference vector to offset p0-p1 'offset' units in direction specified by 'side'
compute_offset_vector(const SkPoint & p0,const SkPoint & p1,SkScalar offset,int side,SkPoint * vector)64 bool compute_offset_vector(const SkPoint& p0, const SkPoint& p1, SkScalar offset, int side,
65                            SkPoint* vector) {
66     SkASSERT(side == -1 || side == 1);
67     // if distances are equal, can just outset by the perpendicular
68     SkVector perp = SkVector::Make(p0.fY - p1.fY, p1.fX - p0.fX);
69     if (!perp.setLength(offset*side)) {
70         return false;
71     }
72     *vector = perp;
73     return true;
74 }
75 
76 // check interval to see if intersection is in segment
outside_interval(SkScalar numer,SkScalar denom,bool denomPositive)77 static inline bool outside_interval(SkScalar numer, SkScalar denom, bool denomPositive) {
78     return (denomPositive && (numer < 0 || numer > denom)) ||
79            (!denomPositive && (numer > 0 || numer < denom));
80 }
81 
82 // Compute the intersection 'p' between segments s0 and s1, if any.
83 // 's' is the parametric value for the intersection along 's0' & 't' is the same for 's1'.
84 // Returns false if there is no intersection.
compute_intersection(const OffsetSegment & s0,const OffsetSegment & s1,SkPoint * p,SkScalar * s,SkScalar * t)85 static bool compute_intersection(const OffsetSegment& s0, const OffsetSegment& s1,
86                                  SkPoint* p, SkScalar* s, SkScalar* t) {
87     const SkVector& v0 = s0.fV;
88     const SkVector& v1 = s1.fV;
89     SkVector w = s1.fP0 - s0.fP0;
90     SkScalar denom = v0.cross(v1);
91     bool denomPositive = (denom > 0);
92     SkScalar sNumer, tNumer;
93     if (SkScalarNearlyZero(denom, kCrossTolerance)) {
94         // segments are parallel, but not collinear
95         if (!SkScalarNearlyZero(w.cross(v0), kCrossTolerance) ||
96             !SkScalarNearlyZero(w.cross(v1), kCrossTolerance)) {
97             return false;
98         }
99 
100         // Check for zero-length segments
101         if (!SkPointPriv::CanNormalize(v0.fX, v0.fY)) {
102             // Both are zero-length
103             if (!SkPointPriv::CanNormalize(v1.fX, v1.fY)) {
104                 // Check if they're the same point
105                 if (!SkPointPriv::CanNormalize(w.fX, w.fY)) {
106                     *p = s0.fP0;
107                     *s = 0;
108                     *t = 0;
109                     return true;
110                 } else {
111                     return false;
112                 }
113             }
114             // Otherwise project segment0's origin onto segment1
115             tNumer = v1.dot(-w);
116             denom = v1.dot(v1);
117             if (outside_interval(tNumer, denom, true)) {
118                 return false;
119             }
120             sNumer = 0;
121         } else {
122             // Project segment1's endpoints onto segment0
123             sNumer = v0.dot(w);
124             denom = v0.dot(v0);
125             tNumer = 0;
126             if (outside_interval(sNumer, denom, true)) {
127                 // The first endpoint doesn't lie on segment0
128                 // If segment1 is degenerate, then there's no collision
129                 if (!SkPointPriv::CanNormalize(v1.fX, v1.fY)) {
130                     return false;
131                 }
132 
133                 // Otherwise try the other one
134                 SkScalar oldSNumer = sNumer;
135                 sNumer = v0.dot(w + v1);
136                 tNumer = denom;
137                 if (outside_interval(sNumer, denom, true)) {
138                     // it's possible that segment1's interval surrounds segment0
139                     // this is false if params have the same signs, and in that case no collision
140                     if (sNumer*oldSNumer > 0) {
141                         return false;
142                     }
143                     // otherwise project segment0's endpoint onto segment1 instead
144                     sNumer = 0;
145                     tNumer = v1.dot(-w);
146                     denom = v1.dot(v1);
147                 }
148             }
149         }
150     } else {
151         sNumer = w.cross(v1);
152         if (outside_interval(sNumer, denom, denomPositive)) {
153             return false;
154         }
155         tNumer = w.cross(v0);
156         if (outside_interval(tNumer, denom, denomPositive)) {
157             return false;
158         }
159     }
160 
161     SkScalar localS = sNumer/denom;
162     SkScalar localT = tNumer/denom;
163 
164     *p = s0.fP0 + v0*localS;
165     *s = localS;
166     *t = localT;
167 
168     return true;
169 }
170 
SkIsConvexPolygon(const SkPoint * polygonVerts,int polygonSize)171 bool SkIsConvexPolygon(const SkPoint* polygonVerts, int polygonSize) {
172     if (polygonSize < 3) {
173         return false;
174     }
175 
176     SkScalar lastArea = 0;
177     SkScalar lastPerpDot = 0;
178 
179     int prevIndex = polygonSize - 1;
180     int currIndex = 0;
181     int nextIndex = 1;
182     SkPoint origin = polygonVerts[0];
183     SkVector v0 = polygonVerts[currIndex] - polygonVerts[prevIndex];
184     SkVector v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
185     SkVector w0 = polygonVerts[currIndex] - origin;
186     SkVector w1 = polygonVerts[nextIndex] - origin;
187     for (int i = 0; i < polygonSize; ++i) {
188         if (!polygonVerts[i].isFinite()) {
189             return false;
190         }
191 
192         // Check that winding direction is always the same (otherwise we have a reflex vertex)
193         SkScalar perpDot = v0.cross(v1);
194         if (lastPerpDot*perpDot < 0) {
195             return false;
196         }
197         if (0 != perpDot) {
198             lastPerpDot = perpDot;
199         }
200 
201         // If the signed area ever flips it's concave
202         // TODO: see if we can verify convexity only with signed area
203         SkScalar quadArea = w0.cross(w1);
204         if (quadArea*lastArea < 0) {
205             return false;
206         }
207         if (0 != quadArea) {
208             lastArea = quadArea;
209         }
210 
211         prevIndex = currIndex;
212         currIndex = nextIndex;
213         nextIndex = (currIndex + 1) % polygonSize;
214         v0 = v1;
215         v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
216         w0 = w1;
217         w1 = polygonVerts[nextIndex] - origin;
218     }
219 
220     return true;
221 }
222 
223 struct OffsetEdge {
224     OffsetEdge*   fPrev;
225     OffsetEdge*   fNext;
226     OffsetSegment fOffset;
227     SkPoint       fIntersection;
228     SkScalar      fTValue;
229     uint16_t      fIndex;
230     uint16_t      fEnd;
231 
initOffsetEdge232     void init(uint16_t start = 0, uint16_t end = 0) {
233         fIntersection = fOffset.fP0;
234         fTValue = SK_ScalarMin;
235         fIndex = start;
236         fEnd = end;
237     }
238 
239     // special intersection check that looks for endpoint intersection
checkIntersectionOffsetEdge240     bool checkIntersection(const OffsetEdge* that,
241                            SkPoint* p, SkScalar* s, SkScalar* t) {
242         if (this->fEnd == that->fIndex) {
243             SkPoint p1 = this->fOffset.fP0 + this->fOffset.fV;
244             if (SkPointPriv::EqualsWithinTolerance(p1, that->fOffset.fP0)) {
245                 *p = p1;
246                 *s = SK_Scalar1;
247                 *t = 0;
248                 return true;
249             }
250         }
251 
252         return compute_intersection(this->fOffset, that->fOffset, p, s, t);
253     }
254 
255     // computes the line intersection and then the "distance" from that to this
256     // this is really a signed squared distance, where negative means that
257     // the intersection lies inside this->fOffset
computeCrossingDistanceOffsetEdge258     SkScalar computeCrossingDistance(const OffsetEdge* that) {
259         const OffsetSegment& s0 = this->fOffset;
260         const OffsetSegment& s1 = that->fOffset;
261         const SkVector& v0 = s0.fV;
262         const SkVector& v1 = s1.fV;
263 
264         SkScalar denom = v0.cross(v1);
265         if (SkScalarNearlyZero(denom, kCrossTolerance)) {
266             // segments are parallel
267             return SK_ScalarMax;
268         }
269 
270         SkVector w = s1.fP0 - s0.fP0;
271         SkScalar localS = w.cross(v1) / denom;
272         if (localS < 0) {
273             localS = -localS;
274         } else {
275             localS -= SK_Scalar1;
276         }
277 
278         localS *= SkScalarAbs(localS);
279         localS *= v0.dot(v0);
280 
281         return localS;
282     }
283 
284 };
285 
remove_node(const OffsetEdge * node,OffsetEdge ** head)286 static void remove_node(const OffsetEdge* node, OffsetEdge** head) {
287     // remove from linked list
288     node->fPrev->fNext = node->fNext;
289     node->fNext->fPrev = node->fPrev;
290     if (node == *head) {
291         *head = (node->fNext == node) ? nullptr : node->fNext;
292     }
293 }
294 
295 //////////////////////////////////////////////////////////////////////////////////
296 
297 // The objective here is to inset all of the edges by the given distance, and then
298 // remove any invalid inset edges by detecting right-hand turns. In a ccw polygon,
299 // we should only be making left-hand turns (for cw polygons, we use the winding
300 // parameter to reverse this). We detect this by checking whether the second intersection
301 // on an edge is closer to its tail than the first one.
302 //
303 // We might also have the case that there is no intersection between two neighboring inset edges.
304 // In this case, one edge will lie to the right of the other and should be discarded along with
305 // its previous intersection (if any).
306 //
307 // Note: the assumption is that inputPolygon is convex and has no coincident points.
308 //
SkInsetConvexPolygon(const SkPoint * inputPolygonVerts,int inputPolygonSize,SkScalar inset,SkTDArray<SkPoint> * insetPolygon)309 bool SkInsetConvexPolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize,
310                           SkScalar inset, SkTDArray<SkPoint>* insetPolygon) {
311     if (inputPolygonSize < 3) {
312         return false;
313     }
314 
315     // restrict this to match other routines
316     // practically we don't want anything bigger than this anyway
317     if (inputPolygonSize > std::numeric_limits<uint16_t>::max()) {
318         return false;
319     }
320 
321     // get winding direction
322     int winding = SkGetPolygonWinding(inputPolygonVerts, inputPolygonSize);
323     if (0 == winding) {
324         return false;
325     }
326 
327     // set up
328     SkAutoSTMalloc<64, OffsetEdge> edgeData(inputPolygonSize);
329     int prev = inputPolygonSize - 1;
330     for (int curr = 0; curr < inputPolygonSize; prev = curr, ++curr) {
331         int next = (curr + 1) % inputPolygonSize;
332         if (!inputPolygonVerts[curr].isFinite()) {
333             return false;
334         }
335         // check for convexity just to be sure
336         if (compute_side(inputPolygonVerts[prev], inputPolygonVerts[curr] - inputPolygonVerts[prev],
337                          inputPolygonVerts[next])*winding < 0) {
338             return false;
339         }
340         SkVector v = inputPolygonVerts[next] - inputPolygonVerts[curr];
341         SkVector perp = SkVector::Make(-v.fY, v.fX);
342         perp.setLength(inset*winding);
343         edgeData[curr].fPrev = &edgeData[prev];
344         edgeData[curr].fNext = &edgeData[next];
345         edgeData[curr].fOffset.fP0 = inputPolygonVerts[curr] + perp;
346         edgeData[curr].fOffset.fV = v;
347         edgeData[curr].init();
348     }
349 
350     OffsetEdge* head = &edgeData[0];
351     OffsetEdge* currEdge = head;
352     OffsetEdge* prevEdge = currEdge->fPrev;
353     int insetVertexCount = inputPolygonSize;
354     unsigned int iterations = 0;
355     unsigned int maxIterations = inputPolygonSize * inputPolygonSize;
356     while (head && prevEdge != currEdge) {
357         ++iterations;
358         // we should check each edge against each other edge at most once
359         if (iterations > maxIterations) {
360             return false;
361         }
362 
363         SkScalar s, t;
364         SkPoint intersection;
365         if (compute_intersection(prevEdge->fOffset, currEdge->fOffset,
366                                  &intersection, &s, &t)) {
367             // if new intersection is further back on previous inset from the prior intersection
368             if (s < prevEdge->fTValue) {
369                 // no point in considering this one again
370                 remove_node(prevEdge, &head);
371                 --insetVertexCount;
372                 // go back one segment
373                 prevEdge = prevEdge->fPrev;
374             // we've already considered this intersection, we're done
375             } else if (currEdge->fTValue > SK_ScalarMin &&
376                        SkPointPriv::EqualsWithinTolerance(intersection,
377                                                           currEdge->fIntersection,
378                                                           1.0e-6f)) {
379                 break;
380             } else {
381                 // add intersection
382                 currEdge->fIntersection = intersection;
383                 currEdge->fTValue = t;
384 
385                 // go to next segment
386                 prevEdge = currEdge;
387                 currEdge = currEdge->fNext;
388             }
389         } else {
390             // if prev to right side of curr
391             int side = winding*compute_side(currEdge->fOffset.fP0,
392                                             currEdge->fOffset.fV,
393                                             prevEdge->fOffset.fP0);
394             if (side < 0 &&
395                 side == winding*compute_side(currEdge->fOffset.fP0,
396                                              currEdge->fOffset.fV,
397                                              prevEdge->fOffset.fP0 + prevEdge->fOffset.fV)) {
398                 // no point in considering this one again
399                 remove_node(prevEdge, &head);
400                 --insetVertexCount;
401                 // go back one segment
402                 prevEdge = prevEdge->fPrev;
403             } else {
404                 // move to next segment
405                 remove_node(currEdge, &head);
406                 --insetVertexCount;
407                 currEdge = currEdge->fNext;
408             }
409         }
410     }
411 
412     // store all the valid intersections that aren't nearly coincident
413     // TODO: look at the main algorithm and see if we can detect these better
414     insetPolygon->reset();
415     if (!head) {
416         return false;
417     }
418 
419     static constexpr SkScalar kCleanupTolerance = 0.01f;
420     if (insetVertexCount >= 0) {
421         insetPolygon->setReserve(insetVertexCount);
422     }
423     int currIndex = 0;
424     *insetPolygon->push() = head->fIntersection;
425     currEdge = head->fNext;
426     while (currEdge != head) {
427         if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
428                                                 (*insetPolygon)[currIndex],
429                                                 kCleanupTolerance)) {
430             *insetPolygon->push() = currEdge->fIntersection;
431             currIndex++;
432         }
433         currEdge = currEdge->fNext;
434     }
435     // make sure the first and last points aren't coincident
436     if (currIndex >= 1 &&
437         SkPointPriv::EqualsWithinTolerance((*insetPolygon)[0], (*insetPolygon)[currIndex],
438                                             kCleanupTolerance)) {
439         insetPolygon->pop();
440     }
441 
442     return SkIsConvexPolygon(insetPolygon->begin(), insetPolygon->count());
443 }
444 
445 ///////////////////////////////////////////////////////////////////////////////////////////
446 
447 // compute the number of points needed for a circular join when offsetting a reflex vertex
SkComputeRadialSteps(const SkVector & v1,const SkVector & v2,SkScalar offset,SkScalar * rotSin,SkScalar * rotCos,int * n)448 bool SkComputeRadialSteps(const SkVector& v1, const SkVector& v2, SkScalar offset,
449                           SkScalar* rotSin, SkScalar* rotCos, int* n) {
450     const SkScalar kRecipPixelsPerArcSegment = 0.25f;
451 
452     SkScalar rCos = v1.dot(v2);
453     if (!SkScalarIsFinite(rCos)) {
454         return false;
455     }
456     SkScalar rSin = v1.cross(v2);
457     if (!SkScalarIsFinite(rSin)) {
458         return false;
459     }
460     SkScalar theta = SkScalarATan2(rSin, rCos);
461 
462     SkScalar floatSteps = SkScalarAbs(offset*theta*kRecipPixelsPerArcSegment);
463     // limit the number of steps to at most max uint16_t (that's all we can index)
464     // knock one value off the top to account for rounding
465     if (floatSteps >= std::numeric_limits<uint16_t>::max()) {
466         return false;
467     }
468     int steps = SkScalarRoundToInt(floatSteps);
469 
470     SkScalar dTheta = steps > 0 ? theta / steps : 0;
471     *rotSin = SkScalarSinCos(dTheta, rotCos);
472     *n = steps;
473     return true;
474 }
475 
476 ///////////////////////////////////////////////////////////////////////////////////////////
477 
478 // a point is "left" to another if its x-coord is less, or if equal, its y-coord is greater
left(const SkPoint & p0,const SkPoint & p1)479 static bool left(const SkPoint& p0, const SkPoint& p1) {
480     return p0.fX < p1.fX || (!(p0.fX > p1.fX) && p0.fY > p1.fY);
481 }
482 
483 // a point is "right" to another if its x-coord is greater, or if equal, its y-coord is less
right(const SkPoint & p0,const SkPoint & p1)484 static bool right(const SkPoint& p0, const SkPoint& p1) {
485     return p0.fX > p1.fX || (!(p0.fX < p1.fX) && p0.fY < p1.fY);
486 }
487 
488 struct Vertex {
LeftVertex489     static bool Left(const Vertex& qv0, const Vertex& qv1) {
490         return left(qv0.fPosition, qv1.fPosition);
491     }
492 
493     // packed to fit into 16 bytes (one cache line)
494     SkPoint  fPosition;
495     uint16_t fIndex;       // index in unsorted polygon
496     uint16_t fPrevIndex;   // indices for previous and next vertex in unsorted polygon
497     uint16_t fNextIndex;
498     uint16_t fFlags;
499 };
500 
501 enum VertexFlags {
502     kPrevLeft_VertexFlag = 0x1,
503     kNextLeft_VertexFlag = 0x2,
504 };
505 
506 struct ActiveEdge {
ActiveEdgeActiveEdge507     ActiveEdge() : fChild{ nullptr, nullptr }, fAbove(nullptr), fBelow(nullptr), fRed(false) {}
ActiveEdgeActiveEdge508     ActiveEdge(const SkPoint& p0, const SkVector& v, uint16_t index0, uint16_t index1)
509         : fSegment({ p0, v })
510         , fIndex0(index0)
511         , fIndex1(index1)
512         , fAbove(nullptr)
513         , fBelow(nullptr)
514         , fRed(true) {
515         fChild[0] = nullptr;
516         fChild[1] = nullptr;
517     }
518 
519     // Returns true if "this" is above "that", assuming this->p0 is to the left of that->p0
520     // This is only used to verify the edgelist -- the actual test for insertion/deletion is much
521     // simpler because we can make certain assumptions then.
aboveIfLeftActiveEdge522     bool aboveIfLeft(const ActiveEdge* that) const {
523         const SkPoint& p0 = this->fSegment.fP0;
524         const SkPoint& q0 = that->fSegment.fP0;
525         SkASSERT(p0.fX <= q0.fX);
526         SkVector d = q0 - p0;
527         const SkVector& v = this->fSegment.fV;
528         const SkVector& w = that->fSegment.fV;
529         // The idea here is that if the vector between the origins of the two segments (d)
530         // rotates counterclockwise up to the vector representing the "this" segment (v),
531         // then we know that "this" is above "that". If the result is clockwise we say it's below.
532         if (this->fIndex0 != that->fIndex0) {
533             SkScalar cross = d.cross(v);
534             if (cross > kCrossTolerance) {
535                 return true;
536             } else if (cross < -kCrossTolerance) {
537                 return false;
538             }
539         } else if (this->fIndex1 == that->fIndex1) {
540             return false;
541         }
542         // At this point either the two origins are nearly equal or the origin of "that"
543         // lies on dv. So then we try the same for the vector from the tail of "this"
544         // to the head of "that". Again, ccw means "this" is above "that".
545         // d = that.P1 - this.P0
546         //   = that.fP0 + that.fV - this.fP0
547         //   = that.fP0 - this.fP0 + that.fV
548         //   = old_d + that.fV
549         d += w;
550         SkScalar cross = d.cross(v);
551         if (cross > kCrossTolerance) {
552             return true;
553         } else if (cross < -kCrossTolerance) {
554             return false;
555         }
556         // If the previous check fails, the two segments are nearly collinear
557         // First check y-coord of first endpoints
558         if (p0.fX < q0.fX) {
559             return (p0.fY >= q0.fY);
560         } else if (p0.fY > q0.fY) {
561             return true;
562         } else if (p0.fY < q0.fY) {
563             return false;
564         }
565         // The first endpoints are the same, so check the other endpoint
566         SkPoint p1 = p0 + v;
567         SkPoint q1 = q0 + w;
568         if (p1.fX < q1.fX) {
569             return (p1.fY >= q1.fY);
570         } else {
571             return (p1.fY > q1.fY);
572         }
573     }
574 
575     // same as leftAndAbove(), but generalized
aboveActiveEdge576     bool above(const ActiveEdge* that) const {
577         const SkPoint& p0 = this->fSegment.fP0;
578         const SkPoint& q0 = that->fSegment.fP0;
579         if (right(p0, q0)) {
580             return !that->aboveIfLeft(this);
581         } else {
582             return this->aboveIfLeft(that);
583         }
584     }
585 
intersectActiveEdge586     bool intersect(const SkPoint& q0, const SkVector& w, uint16_t index0, uint16_t index1) const {
587         // check first to see if these edges are neighbors in the polygon
588         if (this->fIndex0 == index0 || this->fIndex1 == index0 ||
589             this->fIndex0 == index1 || this->fIndex1 == index1) {
590             return false;
591         }
592 
593         // We don't need the exact intersection point so we can do a simpler test here.
594         const SkPoint& p0 = this->fSegment.fP0;
595         const SkVector& v = this->fSegment.fV;
596         SkPoint p1 = p0 + v;
597         SkPoint q1 = q0 + w;
598 
599         // We assume some x-overlap due to how the edgelist works
600         // This allows us to simplify our test
601         // We need some slop here because storing the vector and recomputing the second endpoint
602         // doesn't necessary give us the original result in floating point.
603         // TODO: Store vector as double? Store endpoint as well?
604         SkASSERT(q0.fX <= p1.fX + SK_ScalarNearlyZero);
605 
606         // if each segment straddles the other (i.e., the endpoints have different sides)
607         // then they intersect
608         bool result;
609         if (p0.fX < q0.fX) {
610             if (q1.fX < p1.fX) {
611                 result = (compute_side(p0, v, q0)*compute_side(p0, v, q1) < 0);
612             } else {
613                 result = (compute_side(p0, v, q0)*compute_side(q0, w, p1) > 0);
614             }
615         } else {
616             if (p1.fX < q1.fX) {
617                 result = (compute_side(q0, w, p0)*compute_side(q0, w, p1) < 0);
618             } else {
619                 result = (compute_side(q0, w, p0)*compute_side(p0, v, q1) > 0);
620             }
621         }
622         return result;
623     }
624 
intersectActiveEdge625     bool intersect(const ActiveEdge* edge) {
626         return this->intersect(edge->fSegment.fP0, edge->fSegment.fV, edge->fIndex0, edge->fIndex1);
627     }
628 
lessThanActiveEdge629     bool lessThan(const ActiveEdge* that) const {
630         SkASSERT(!this->above(this));
631         SkASSERT(!that->above(that));
632         SkASSERT(!(this->above(that) && that->above(this)));
633         return this->above(that);
634     }
635 
equalsActiveEdge636     bool equals(uint16_t index0, uint16_t index1) const {
637         return (this->fIndex0 == index0 && this->fIndex1 == index1);
638     }
639 
640     OffsetSegment fSegment;
641     uint16_t fIndex0;   // indices for previous and next vertex in polygon
642     uint16_t fIndex1;
643     ActiveEdge* fChild[2];
644     ActiveEdge* fAbove;
645     ActiveEdge* fBelow;
646     int32_t  fRed;
647 };
648 
649 class ActiveEdgeList {
650 public:
ActiveEdgeList(int maxEdges)651     ActiveEdgeList(int maxEdges) {
652         fAllocation = (char*) sk_malloc_throw(sizeof(ActiveEdge)*maxEdges);
653         fCurrFree = 0;
654         fMaxFree = maxEdges;
655     }
~ActiveEdgeList()656     ~ActiveEdgeList() {
657         fTreeHead.fChild[1] = nullptr;
658         sk_free(fAllocation);
659     }
660 
insert(const SkPoint & p0,const SkPoint & p1,uint16_t index0,uint16_t index1)661     bool insert(const SkPoint& p0, const SkPoint& p1, uint16_t index0, uint16_t index1) {
662         SkVector v = p1 - p0;
663         if (!v.isFinite()) {
664             return false;
665         }
666         // empty tree case -- easy
667         if (!fTreeHead.fChild[1]) {
668             ActiveEdge* root = fTreeHead.fChild[1] = this->allocate(p0, v, index0, index1);
669             SkASSERT(root);
670             if (!root) {
671                 return false;
672             }
673             root->fRed = false;
674             return true;
675         }
676 
677         // set up helpers
678         ActiveEdge* top = &fTreeHead;
679         ActiveEdge *grandparent = nullptr;
680         ActiveEdge *parent = nullptr;
681         ActiveEdge *curr = top->fChild[1];
682         int dir = 0;
683         int last = 0; // ?
684         // predecessor and successor, for intersection check
685         ActiveEdge* pred = nullptr;
686         ActiveEdge* succ = nullptr;
687 
688         // search down the tree
689         while (true) {
690             if (!curr) {
691                 // check for intersection with predecessor and successor
692                 if ((pred && pred->intersect(p0, v, index0, index1)) ||
693                     (succ && succ->intersect(p0, v, index0, index1))) {
694                     return false;
695                 }
696                 // insert new node at bottom
697                 parent->fChild[dir] = curr = this->allocate(p0, v, index0, index1);
698                 SkASSERT(curr);
699                 if (!curr) {
700                     return false;
701                 }
702                 curr->fAbove = pred;
703                 curr->fBelow = succ;
704                 if (pred) {
705                     pred->fBelow = curr;
706                 }
707                 if (succ) {
708                     succ->fAbove = curr;
709                 }
710                 if (IsRed(parent)) {
711                     int dir2 = (top->fChild[1] == grandparent);
712                     if (curr == parent->fChild[last]) {
713                         top->fChild[dir2] = SingleRotation(grandparent, !last);
714                     } else {
715                         top->fChild[dir2] = DoubleRotation(grandparent, !last);
716                     }
717                 }
718                 break;
719             } else if (IsRed(curr->fChild[0]) && IsRed(curr->fChild[1])) {
720                 // color flip
721                 curr->fRed = true;
722                 curr->fChild[0]->fRed = false;
723                 curr->fChild[1]->fRed = false;
724                 if (IsRed(parent)) {
725                     int dir2 = (top->fChild[1] == grandparent);
726                     if (curr == parent->fChild[last]) {
727                         top->fChild[dir2] = SingleRotation(grandparent, !last);
728                     } else {
729                         top->fChild[dir2] = DoubleRotation(grandparent, !last);
730                     }
731                 }
732             }
733 
734             last = dir;
735             int side;
736             // check to see if segment is above or below
737             if (curr->fIndex0 == index0) {
738                 side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p1);
739             } else {
740                 side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p0);
741             }
742             if (0 == side) {
743                 return false;
744             }
745             dir = (side < 0);
746 
747             if (0 == dir) {
748                 succ = curr;
749             } else {
750                 pred = curr;
751             }
752 
753             // update helpers
754             if (grandparent) {
755                 top = grandparent;
756             }
757             grandparent = parent;
758             parent = curr;
759             curr = curr->fChild[dir];
760         }
761 
762         // update root and make it black
763         fTreeHead.fChild[1]->fRed = false;
764 
765         SkDEBUGCODE(VerifyTree(fTreeHead.fChild[1]));
766 
767         return true;
768     }
769 
770     // replaces edge p0p1 with p1p2
replace(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,uint16_t index0,uint16_t index1,uint16_t index2)771     bool replace(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
772                  uint16_t index0, uint16_t index1, uint16_t index2) {
773         if (!fTreeHead.fChild[1]) {
774             return false;
775         }
776 
777         SkVector v = p2 - p1;
778         ActiveEdge* curr = &fTreeHead;
779         ActiveEdge* found = nullptr;
780         int dir = 1;
781 
782         // search
783         while (curr->fChild[dir] != nullptr) {
784             // update helpers
785             curr = curr->fChild[dir];
786             // save found node
787             if (curr->equals(index0, index1)) {
788                 found = curr;
789                 break;
790             } else {
791                 // check to see if segment is above or below
792                 int side;
793                 if (curr->fIndex1 == index1) {
794                     side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p0);
795                 } else {
796                     side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p1);
797                 }
798                 if (0 == side) {
799                     return false;
800                 }
801                 dir = (side < 0);
802             }
803         }
804 
805         if (!found) {
806             return false;
807         }
808 
809         // replace if found
810         ActiveEdge* pred = found->fAbove;
811         ActiveEdge* succ = found->fBelow;
812         // check deletion and insert intersection cases
813         if (pred && (pred->intersect(found) || pred->intersect(p1, v, index1, index2))) {
814             return false;
815         }
816         if (succ && (succ->intersect(found) || succ->intersect(p1, v, index1, index2))) {
817             return false;
818         }
819         found->fSegment.fP0 = p1;
820         found->fSegment.fV = v;
821         found->fIndex0 = index1;
822         found->fIndex1 = index2;
823         // above and below should stay the same
824 
825         SkDEBUGCODE(VerifyTree(fTreeHead.fChild[1]));
826 
827         return true;
828     }
829 
remove(const SkPoint & p0,const SkPoint & p1,uint16_t index0,uint16_t index1)830     bool remove(const SkPoint& p0, const SkPoint& p1, uint16_t index0, uint16_t index1) {
831         if (!fTreeHead.fChild[1]) {
832             return false;
833         }
834 
835         ActiveEdge* curr = &fTreeHead;
836         ActiveEdge* parent = nullptr;
837         ActiveEdge* grandparent = nullptr;
838         ActiveEdge* found = nullptr;
839         int dir = 1;
840 
841         // search and push a red node down
842         while (curr->fChild[dir] != nullptr) {
843             int last = dir;
844 
845             // update helpers
846             grandparent = parent;
847             parent = curr;
848             curr = curr->fChild[dir];
849             // save found node
850             if (curr->equals(index0, index1)) {
851                 found = curr;
852                 dir = 0;
853             } else {
854                 // check to see if segment is above or below
855                 int side;
856                 if (curr->fIndex1 == index1) {
857                     side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p0);
858                 } else {
859                     side = compute_side(curr->fSegment.fP0, curr->fSegment.fV, p1);
860                 }
861                 if (0 == side) {
862                     return false;
863                 }
864                 dir = (side < 0);
865             }
866 
867             // push the red node down
868             if (!IsRed(curr) && !IsRed(curr->fChild[dir])) {
869                 if (IsRed(curr->fChild[!dir])) {
870                     parent = parent->fChild[last] = SingleRotation(curr, dir);
871                 } else {
872                     ActiveEdge *s = parent->fChild[!last];
873 
874                     if (s != NULL) {
875                         if (!IsRed(s->fChild[!last]) && !IsRed(s->fChild[last])) {
876                             // color flip
877                             parent->fRed = false;
878                             s->fRed = true;
879                             curr->fRed = true;
880                         } else {
881                             int dir2 = (grandparent->fChild[1] == parent);
882 
883                             if (IsRed(s->fChild[last])) {
884                                 grandparent->fChild[dir2] = DoubleRotation(parent, last);
885                             } else if (IsRed(s->fChild[!last])) {
886                                 grandparent->fChild[dir2] = SingleRotation(parent, last);
887                             }
888 
889                             // ensure correct coloring
890                             curr->fRed = grandparent->fChild[dir2]->fRed = true;
891                             grandparent->fChild[dir2]->fChild[0]->fRed = false;
892                             grandparent->fChild[dir2]->fChild[1]->fRed = false;
893                         }
894                     }
895                 }
896             }
897         }
898 
899         // replace and remove if found
900         if (found) {
901             ActiveEdge* pred = found->fAbove;
902             ActiveEdge* succ = found->fBelow;
903             if ((pred && pred->intersect(found)) || (succ && succ->intersect(found))) {
904                 return false;
905             }
906             if (found != curr) {
907                 found->fSegment = curr->fSegment;
908                 found->fIndex0 = curr->fIndex0;
909                 found->fIndex1 = curr->fIndex1;
910                 found->fAbove = curr->fAbove;
911                 pred = found->fAbove;
912                 // we don't need to set found->fBelow here
913             } else {
914                 if (succ) {
915                     succ->fAbove = pred;
916                 }
917             }
918             if (pred) {
919                 pred->fBelow = curr->fBelow;
920             }
921             parent->fChild[parent->fChild[1] == curr] = curr->fChild[!curr->fChild[0]];
922 
923             // no need to delete
924             curr->fAbove = reinterpret_cast<ActiveEdge*>(0xdeadbeefll);
925             curr->fBelow = reinterpret_cast<ActiveEdge*>(0xdeadbeefll);
926             if (fTreeHead.fChild[1]) {
927                 fTreeHead.fChild[1]->fRed = false;
928             }
929         }
930 
931         // update root and make it black
932         if (fTreeHead.fChild[1]) {
933             fTreeHead.fChild[1]->fRed = false;
934         }
935 
936         SkDEBUGCODE(VerifyTree(fTreeHead.fChild[1]));
937 
938         return true;
939     }
940 
941 private:
942     // allocator
allocate(const SkPoint & p0,const SkPoint & p1,uint16_t index0,uint16_t index1)943     ActiveEdge * allocate(const SkPoint& p0, const SkPoint& p1, uint16_t index0, uint16_t index1) {
944         if (fCurrFree >= fMaxFree) {
945             return nullptr;
946         }
947         char* bytes = fAllocation + sizeof(ActiveEdge)*fCurrFree;
948         ++fCurrFree;
949         return new(bytes) ActiveEdge(p0, p1, index0, index1);
950     }
951 
952     ///////////////////////////////////////////////////////////////////////////////////
953     // Red-black tree methods
954     ///////////////////////////////////////////////////////////////////////////////////
IsRed(const ActiveEdge * node)955     static bool IsRed(const ActiveEdge* node) {
956         return node && node->fRed;
957     }
958 
SingleRotation(ActiveEdge * node,int dir)959     static ActiveEdge* SingleRotation(ActiveEdge* node, int dir) {
960         ActiveEdge* tmp = node->fChild[!dir];
961 
962         node->fChild[!dir] = tmp->fChild[dir];
963         tmp->fChild[dir] = node;
964 
965         node->fRed = true;
966         tmp->fRed = false;
967 
968         return tmp;
969     }
970 
DoubleRotation(ActiveEdge * node,int dir)971     static ActiveEdge* DoubleRotation(ActiveEdge* node, int dir) {
972         node->fChild[!dir] = SingleRotation(node->fChild[!dir], !dir);
973 
974         return SingleRotation(node, dir);
975     }
976 
977     // returns black link count
VerifyTree(const ActiveEdge * tree)978     static int VerifyTree(const ActiveEdge* tree) {
979         if (!tree) {
980             return 1;
981         }
982 
983         const ActiveEdge* left = tree->fChild[0];
984         const ActiveEdge* right = tree->fChild[1];
985 
986         // no consecutive red links
987         if (IsRed(tree) && (IsRed(left) || IsRed(right))) {
988             SkASSERT(false);
989             return 0;
990         }
991 
992         // check secondary links
993         if (tree->fAbove) {
994             SkASSERT(tree->fAbove->fBelow == tree);
995             SkASSERT(tree->fAbove->lessThan(tree));
996         }
997         if (tree->fBelow) {
998             SkASSERT(tree->fBelow->fAbove == tree);
999             SkASSERT(tree->lessThan(tree->fBelow));
1000         }
1001 
1002         // violates binary tree order
1003         if ((left && tree->lessThan(left)) || (right && right->lessThan(tree))) {
1004             SkASSERT(false);
1005             return 0;
1006         }
1007 
1008         int leftCount = VerifyTree(left);
1009         int rightCount = VerifyTree(right);
1010 
1011         // return black link count
1012         if (leftCount != 0 && rightCount != 0) {
1013             // black height mismatch
1014             if (leftCount != rightCount) {
1015                 SkASSERT(false);
1016                 return 0;
1017             }
1018             return IsRed(tree) ? leftCount : leftCount + 1;
1019         } else {
1020             return 0;
1021         }
1022     }
1023 
1024     ActiveEdge fTreeHead;
1025     char*      fAllocation;
1026     int        fCurrFree;
1027     int        fMaxFree;
1028 };
1029 
1030 // Here we implement a sweep line algorithm to determine whether the provided points
1031 // represent a simple polygon, i.e., the polygon is non-self-intersecting.
1032 // We first insert the vertices into a priority queue sorting horizontally from left to right.
1033 // Then as we pop the vertices from the queue we generate events which indicate that an edge
1034 // should be added or removed from an edge list. If any intersections are detected in the edge
1035 // list, then we know the polygon is self-intersecting and hence not simple.
SkIsSimplePolygon(const SkPoint * polygon,int polygonSize)1036 bool SkIsSimplePolygon(const SkPoint* polygon, int polygonSize) {
1037     if (polygonSize < 3) {
1038         return false;
1039     }
1040 
1041     // need to be able to represent all the vertices in the 16-bit indices
1042     if (polygonSize > std::numeric_limits<uint16_t>::max()) {
1043         return false;
1044     }
1045 
1046     // If it's convex, it's simple
1047     if (SkIsConvexPolygon(polygon, polygonSize)) {
1048         return true;
1049     }
1050 
1051     SkTDPQueue <Vertex, Vertex::Left> vertexQueue(polygonSize);
1052     for (int i = 0; i < polygonSize; ++i) {
1053         Vertex newVertex;
1054         if (!polygon[i].isFinite()) {
1055             return false;
1056         }
1057         newVertex.fPosition = polygon[i];
1058         newVertex.fIndex = i;
1059         newVertex.fPrevIndex = (i - 1 + polygonSize) % polygonSize;
1060         newVertex.fNextIndex = (i + 1) % polygonSize;
1061         newVertex.fFlags = 0;
1062         if (left(polygon[newVertex.fPrevIndex], polygon[i])) {
1063             newVertex.fFlags |= kPrevLeft_VertexFlag;
1064         }
1065         if (left(polygon[newVertex.fNextIndex], polygon[i])) {
1066             newVertex.fFlags |= kNextLeft_VertexFlag;
1067         }
1068         vertexQueue.insert(newVertex);
1069     }
1070 
1071     // pop each vertex from the queue and generate events depending on
1072     // where it lies relative to its neighboring edges
1073     ActiveEdgeList sweepLine(polygonSize);
1074     while (vertexQueue.count() > 0) {
1075         const Vertex& v = vertexQueue.peek();
1076 
1077         // both to the right -- insert both
1078         if (v.fFlags == 0) {
1079             if (!sweepLine.insert(v.fPosition, polygon[v.fPrevIndex], v.fIndex, v.fPrevIndex)) {
1080                 break;
1081             }
1082             if (!sweepLine.insert(v.fPosition, polygon[v.fNextIndex], v.fIndex, v.fNextIndex)) {
1083                 break;
1084             }
1085         // both to the left -- remove both
1086         } else if (v.fFlags == (kPrevLeft_VertexFlag | kNextLeft_VertexFlag)) {
1087             if (!sweepLine.remove(polygon[v.fPrevIndex], v.fPosition, v.fPrevIndex, v.fIndex)) {
1088                 break;
1089             }
1090             if (!sweepLine.remove(polygon[v.fNextIndex], v.fPosition, v.fNextIndex, v.fIndex)) {
1091                 break;
1092             }
1093         // one to left and right -- replace one with another
1094         } else {
1095             if (v.fFlags & kPrevLeft_VertexFlag) {
1096                 if (!sweepLine.replace(polygon[v.fPrevIndex], v.fPosition, polygon[v.fNextIndex],
1097                                        v.fPrevIndex, v.fIndex, v.fNextIndex)) {
1098                     break;
1099                 }
1100             } else {
1101                 SkASSERT(v.fFlags & kNextLeft_VertexFlag);
1102                 if (!sweepLine.replace(polygon[v.fNextIndex], v.fPosition, polygon[v.fPrevIndex],
1103                                        v.fNextIndex, v.fIndex, v.fPrevIndex)) {
1104                     break;
1105                 }
1106             }
1107         }
1108 
1109         vertexQueue.pop();
1110     }
1111 
1112     return (vertexQueue.count() == 0);
1113 }
1114 
1115 ///////////////////////////////////////////////////////////////////////////////////////////
1116 
1117 // helper function for SkOffsetSimplePolygon
setup_offset_edge(OffsetEdge * currEdge,const SkPoint & endpoint0,const SkPoint & endpoint1,uint16_t startIndex,uint16_t endIndex)1118 static void setup_offset_edge(OffsetEdge* currEdge,
1119                               const SkPoint& endpoint0, const SkPoint& endpoint1,
1120                               uint16_t startIndex, uint16_t endIndex) {
1121     currEdge->fOffset.fP0 = endpoint0;
1122     currEdge->fOffset.fV = endpoint1 - endpoint0;
1123     currEdge->init(startIndex, endIndex);
1124 }
1125 
is_reflex_vertex(const SkPoint * inputPolygonVerts,int winding,SkScalar offset,uint16_t prevIndex,uint16_t currIndex,uint16_t nextIndex)1126 static bool is_reflex_vertex(const SkPoint* inputPolygonVerts, int winding, SkScalar offset,
1127                              uint16_t prevIndex, uint16_t currIndex, uint16_t nextIndex) {
1128     int side = compute_side(inputPolygonVerts[prevIndex],
1129                             inputPolygonVerts[currIndex] - inputPolygonVerts[prevIndex],
1130                             inputPolygonVerts[nextIndex]);
1131     // if reflex point, we need to add extra edges
1132     return (side*winding*offset < 0);
1133 }
1134 
SkOffsetSimplePolygon(const SkPoint * inputPolygonVerts,int inputPolygonSize,SkScalar offset,SkTDArray<SkPoint> * offsetPolygon,SkTDArray<int> * polygonIndices)1135 bool SkOffsetSimplePolygon(const SkPoint* inputPolygonVerts, int inputPolygonSize, SkScalar offset,
1136                            SkTDArray<SkPoint>* offsetPolygon, SkTDArray<int>* polygonIndices) {
1137     if (inputPolygonSize < 3) {
1138         return false;
1139     }
1140 
1141     // need to be able to represent all the vertices in the 16-bit indices
1142     if (inputPolygonSize >= std::numeric_limits<uint16_t>::max()) {
1143         return false;
1144     }
1145 
1146     if (!SkScalarIsFinite(offset)) {
1147         return false;
1148     }
1149 
1150     // get winding direction
1151     int winding = SkGetPolygonWinding(inputPolygonVerts, inputPolygonSize);
1152     if (0 == winding) {
1153         return false;
1154     }
1155 
1156     // build normals
1157     SkAutoSTMalloc<64, SkVector> normals(inputPolygonSize);
1158     unsigned int numEdges = 0;
1159     for (int currIndex = 0, prevIndex = inputPolygonSize - 1;
1160          currIndex < inputPolygonSize;
1161          prevIndex = currIndex, ++currIndex) {
1162         if (!inputPolygonVerts[currIndex].isFinite()) {
1163             return false;
1164         }
1165         int nextIndex = (currIndex + 1) % inputPolygonSize;
1166         if (!compute_offset_vector(inputPolygonVerts[currIndex], inputPolygonVerts[nextIndex],
1167                                    offset, winding, &normals[currIndex])) {
1168             return false;
1169         }
1170         if (currIndex > 0) {
1171             // if reflex point, we need to add extra edges
1172             if (is_reflex_vertex(inputPolygonVerts, winding, offset,
1173                                  prevIndex, currIndex, nextIndex)) {
1174                 SkScalar rotSin, rotCos;
1175                 int numSteps;
1176                 if (!SkComputeRadialSteps(normals[prevIndex], normals[currIndex], offset,
1177                                           &rotSin, &rotCos, &numSteps)) {
1178                     return false;
1179                 }
1180                 numEdges += SkTMax(numSteps, 1);
1181             }
1182         }
1183         numEdges++;
1184     }
1185     // finish up the edge counting
1186     if (is_reflex_vertex(inputPolygonVerts, winding, offset, inputPolygonSize-1, 0, 1)) {
1187         SkScalar rotSin, rotCos;
1188         int numSteps;
1189         if (!SkComputeRadialSteps(normals[inputPolygonSize-1], normals[0], offset,
1190                                   &rotSin, &rotCos, &numSteps)) {
1191             return false;
1192         }
1193         numEdges += SkTMax(numSteps, 1);
1194     }
1195 
1196     // Make sure we don't overflow the max array count.
1197     // We shouldn't overflow numEdges, as SkComputeRadialSteps returns a max of 2^16-1,
1198     // and we have a max of 2^16-1 original vertices.
1199     if (numEdges > (unsigned int)std::numeric_limits<int32_t>::max()) {
1200         return false;
1201     }
1202 
1203     // build initial offset edge list
1204     SkSTArray<64, OffsetEdge> edgeData(numEdges);
1205     OffsetEdge* prevEdge = nullptr;
1206     for (int currIndex = 0, prevIndex = inputPolygonSize - 1;
1207          currIndex < inputPolygonSize;
1208          prevIndex = currIndex, ++currIndex) {
1209         int nextIndex = (currIndex + 1) % inputPolygonSize;
1210         // if reflex point, fill in curve
1211         if (is_reflex_vertex(inputPolygonVerts, winding, offset,
1212                              prevIndex, currIndex, nextIndex)) {
1213             SkScalar rotSin, rotCos;
1214             int numSteps;
1215             SkVector prevNormal = normals[prevIndex];
1216             if (!SkComputeRadialSteps(prevNormal, normals[currIndex], offset,
1217                                       &rotSin, &rotCos, &numSteps)) {
1218                 return false;
1219             }
1220             auto currEdge = edgeData.push_back_n(SkTMax(numSteps, 1));
1221             for (int i = 0; i < numSteps - 1; ++i) {
1222                 SkVector currNormal = SkVector::Make(prevNormal.fX*rotCos - prevNormal.fY*rotSin,
1223                                                      prevNormal.fY*rotCos + prevNormal.fX*rotSin);
1224                 setup_offset_edge(currEdge,
1225                                   inputPolygonVerts[currIndex] + prevNormal,
1226                                   inputPolygonVerts[currIndex] + currNormal,
1227                                   currIndex, currIndex);
1228                 prevNormal = currNormal;
1229                 currEdge->fPrev = prevEdge;
1230                 if (prevEdge) {
1231                     prevEdge->fNext = currEdge;
1232                 }
1233                 prevEdge = currEdge;
1234                 ++currEdge;
1235             }
1236             setup_offset_edge(currEdge,
1237                               inputPolygonVerts[currIndex] + prevNormal,
1238                               inputPolygonVerts[currIndex] + normals[currIndex],
1239                               currIndex, currIndex);
1240             currEdge->fPrev = prevEdge;
1241             if (prevEdge) {
1242                 prevEdge->fNext = currEdge;
1243             }
1244             prevEdge = currEdge;
1245         }
1246 
1247         // Add the edge
1248         auto currEdge = edgeData.push_back_n(1);
1249         setup_offset_edge(currEdge,
1250                           inputPolygonVerts[currIndex] + normals[currIndex],
1251                           inputPolygonVerts[nextIndex] + normals[currIndex],
1252                           currIndex, nextIndex);
1253         currEdge->fPrev = prevEdge;
1254         if (prevEdge) {
1255             prevEdge->fNext = currEdge;
1256         }
1257         prevEdge = currEdge;
1258     }
1259     // close up the linked list
1260     SkASSERT(prevEdge);
1261     prevEdge->fNext = &edgeData[0];
1262     edgeData[0].fPrev = prevEdge;
1263 
1264     // now clip edges
1265     SkASSERT(edgeData.count() == (int)numEdges);
1266     auto head = &edgeData[0];
1267     auto currEdge = head;
1268     unsigned int offsetVertexCount = numEdges;
1269     unsigned long long iterations = 0;
1270     unsigned long long maxIterations = (unsigned long long)(numEdges) * numEdges;
1271     while (head && prevEdge != currEdge && offsetVertexCount > 0) {
1272         ++iterations;
1273         // we should check each edge against each other edge at most once
1274         if (iterations > maxIterations) {
1275             return false;
1276         }
1277 
1278         SkScalar s, t;
1279         SkPoint intersection;
1280         if (prevEdge->checkIntersection(currEdge, &intersection, &s, &t)) {
1281             // if new intersection is further back on previous inset from the prior intersection
1282             if (s < prevEdge->fTValue) {
1283                 // no point in considering this one again
1284                 remove_node(prevEdge, &head);
1285                 --offsetVertexCount;
1286                 // go back one segment
1287                 prevEdge = prevEdge->fPrev;
1288                 // we've already considered this intersection, we're done
1289             } else if (currEdge->fTValue > SK_ScalarMin &&
1290                        SkPointPriv::EqualsWithinTolerance(intersection,
1291                                                           currEdge->fIntersection,
1292                                                           1.0e-6f)) {
1293                 break;
1294             } else {
1295                 // add intersection
1296                 currEdge->fIntersection = intersection;
1297                 currEdge->fTValue = t;
1298                 currEdge->fIndex = prevEdge->fEnd;
1299 
1300                 // go to next segment
1301                 prevEdge = currEdge;
1302                 currEdge = currEdge->fNext;
1303             }
1304         } else {
1305             // If there is no intersection, we want to minimize the distance between
1306             // the point where the segment lines cross and the segments themselves.
1307             OffsetEdge* prevPrevEdge = prevEdge->fPrev;
1308             OffsetEdge* currNextEdge = currEdge->fNext;
1309             SkScalar dist0 = currEdge->computeCrossingDistance(prevPrevEdge);
1310             SkScalar dist1 = prevEdge->computeCrossingDistance(currNextEdge);
1311             // if both lead to direct collision
1312             if (dist0 < 0 && dist1 < 0) {
1313                 // check first to see if either represent parts of one contour
1314                 SkPoint p1 = prevPrevEdge->fOffset.fP0 + prevPrevEdge->fOffset.fV;
1315                 bool prevSameContour = SkPointPriv::EqualsWithinTolerance(p1,
1316                                                                           prevEdge->fOffset.fP0);
1317                 p1 = currEdge->fOffset.fP0 + currEdge->fOffset.fV;
1318                 bool currSameContour = SkPointPriv::EqualsWithinTolerance(p1,
1319                                                                          currNextEdge->fOffset.fP0);
1320 
1321                 // want to step along contour to find intersections rather than jump to new one
1322                 if (currSameContour && !prevSameContour) {
1323                     remove_node(currEdge, &head);
1324                     currEdge = currNextEdge;
1325                     --offsetVertexCount;
1326                     continue;
1327                 } else if (prevSameContour && !currSameContour) {
1328                     remove_node(prevEdge, &head);
1329                     prevEdge = prevPrevEdge;
1330                     --offsetVertexCount;
1331                     continue;
1332                 }
1333             }
1334 
1335             // otherwise minimize collision distance along segment
1336             if (dist0 < dist1) {
1337                 remove_node(prevEdge, &head);
1338                 prevEdge = prevPrevEdge;
1339             } else {
1340                 remove_node(currEdge, &head);
1341                 currEdge = currNextEdge;
1342             }
1343             --offsetVertexCount;
1344         }
1345     }
1346 
1347     // store all the valid intersections that aren't nearly coincident
1348     // TODO: look at the main algorithm and see if we can detect these better
1349     offsetPolygon->reset();
1350     if (!head || offsetVertexCount == 0 ||
1351         offsetVertexCount >= std::numeric_limits<uint16_t>::max()) {
1352         return false;
1353     }
1354 
1355     static constexpr SkScalar kCleanupTolerance = 0.01f;
1356     offsetPolygon->setReserve(offsetVertexCount);
1357     int currIndex = 0;
1358     *offsetPolygon->push() = head->fIntersection;
1359     if (polygonIndices) {
1360         *polygonIndices->push() = head->fIndex;
1361     }
1362     currEdge = head->fNext;
1363     while (currEdge != head) {
1364         if (!SkPointPriv::EqualsWithinTolerance(currEdge->fIntersection,
1365                                                 (*offsetPolygon)[currIndex],
1366                                                 kCleanupTolerance)) {
1367             *offsetPolygon->push() = currEdge->fIntersection;
1368             if (polygonIndices) {
1369                 *polygonIndices->push() = currEdge->fIndex;
1370             }
1371             currIndex++;
1372         }
1373         currEdge = currEdge->fNext;
1374     }
1375     // make sure the first and last points aren't coincident
1376     if (currIndex >= 1 &&
1377         SkPointPriv::EqualsWithinTolerance((*offsetPolygon)[0], (*offsetPolygon)[currIndex],
1378                                             kCleanupTolerance)) {
1379         offsetPolygon->pop();
1380         if (polygonIndices) {
1381             polygonIndices->pop();
1382         }
1383     }
1384 
1385     // check winding of offset polygon (it should be same as the original polygon)
1386     SkScalar offsetWinding = SkGetPolygonWinding(offsetPolygon->begin(), offsetPolygon->count());
1387 
1388     return (winding*offsetWinding > 0 &&
1389             SkIsSimplePolygon(offsetPolygon->begin(), offsetPolygon->count()));
1390 }
1391 
1392 //////////////////////////////////////////////////////////////////////////////////////////
1393 
1394 struct TriangulationVertex {
1395     SK_DECLARE_INTERNAL_LLIST_INTERFACE(TriangulationVertex);
1396 
1397     enum class VertexType { kConvex, kReflex };
1398 
1399     SkPoint    fPosition;
1400     VertexType fVertexType;
1401     uint16_t   fIndex;
1402     uint16_t   fPrevIndex;
1403     uint16_t   fNextIndex;
1404 };
1405 
compute_triangle_bounds(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,SkRect * bounds)1406 static void compute_triangle_bounds(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
1407                                     SkRect* bounds) {
1408     Sk4s min, max;
1409     min = max = Sk4s(p0.fX, p0.fY, p0.fX, p0.fY);
1410     Sk4s xy(p1.fX, p1.fY, p2.fX, p2.fY);
1411     min = Sk4s::Min(min, xy);
1412     max = Sk4s::Max(max, xy);
1413     bounds->set(SkTMin(min[0], min[2]), SkTMin(min[1], min[3]),
1414                 SkTMax(max[0], max[2]), SkTMax(max[1], max[3]));
1415 }
1416 
1417 // test to see if point p is in triangle p0p1p2.
1418 // for now assuming strictly inside -- if on the edge it's outside
point_in_triangle(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,const SkPoint & p)1419 static bool point_in_triangle(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
1420                               const SkPoint& p) {
1421     SkVector v0 = p1 - p0;
1422     SkVector v1 = p2 - p1;
1423     SkScalar n = v0.cross(v1);
1424 
1425     SkVector w0 = p - p0;
1426     if (n*v0.cross(w0) < SK_ScalarNearlyZero) {
1427         return false;
1428     }
1429 
1430     SkVector w1 = p - p1;
1431     if (n*v1.cross(w1) < SK_ScalarNearlyZero) {
1432         return false;
1433     }
1434 
1435     SkVector v2 = p0 - p2;
1436     SkVector w2 = p - p2;
1437     if (n*v2.cross(w2) < SK_ScalarNearlyZero) {
1438         return false;
1439     }
1440 
1441     return true;
1442 }
1443 
1444 // Data structure to track reflex vertices and check whether any are inside a given triangle
1445 class ReflexHash {
1446 public:
init(const SkRect & bounds,int vertexCount)1447     bool init(const SkRect& bounds, int vertexCount) {
1448         fBounds = bounds;
1449         fNumVerts = 0;
1450         SkScalar width = bounds.width();
1451         SkScalar height = bounds.height();
1452         if (!SkScalarIsFinite(width) || !SkScalarIsFinite(height)) {
1453             return false;
1454         }
1455 
1456         // We want vertexCount grid cells, roughly distributed to match the bounds ratio
1457         SkScalar hCount = SkScalarSqrt(sk_ieee_float_divide(vertexCount*width, height));
1458         if (!SkScalarIsFinite(hCount)) {
1459             return false;
1460         }
1461         fHCount = SkTMax(SkTMin(SkScalarRoundToInt(hCount), vertexCount), 1);
1462         fVCount = vertexCount/fHCount;
1463         fGridConversion.set(sk_ieee_float_divide(fHCount - 0.001f, width),
1464                             sk_ieee_float_divide(fVCount - 0.001f, height));
1465         if (!fGridConversion.isFinite()) {
1466             return false;
1467         }
1468 
1469         fGrid.setCount(fHCount*fVCount);
1470         for (int i = 0; i < fGrid.count(); ++i) {
1471             fGrid[i].reset();
1472         }
1473 
1474         return true;
1475     }
1476 
add(TriangulationVertex * v)1477     void add(TriangulationVertex* v) {
1478         int index = hash(v);
1479         fGrid[index].addToTail(v);
1480         ++fNumVerts;
1481     }
1482 
remove(TriangulationVertex * v)1483     void remove(TriangulationVertex* v) {
1484         int index = hash(v);
1485         fGrid[index].remove(v);
1486         --fNumVerts;
1487     }
1488 
checkTriangle(const SkPoint & p0,const SkPoint & p1,const SkPoint & p2,uint16_t ignoreIndex0,uint16_t ignoreIndex1) const1489     bool checkTriangle(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2,
1490                        uint16_t ignoreIndex0, uint16_t ignoreIndex1) const {
1491         if (!fNumVerts) {
1492             return false;
1493         }
1494 
1495         SkRect triBounds;
1496         compute_triangle_bounds(p0, p1, p2, &triBounds);
1497         int h0 = (triBounds.fLeft - fBounds.fLeft)*fGridConversion.fX;
1498         int h1 = (triBounds.fRight - fBounds.fLeft)*fGridConversion.fX;
1499         int v0 = (triBounds.fTop - fBounds.fTop)*fGridConversion.fY;
1500         int v1 = (triBounds.fBottom - fBounds.fTop)*fGridConversion.fY;
1501 
1502         for (int v = v0; v <= v1; ++v) {
1503             for (int h = h0; h <= h1; ++h) {
1504                 int i = v * fHCount + h;
1505                 for (SkTInternalLList<TriangulationVertex>::Iter reflexIter = fGrid[i].begin();
1506                      reflexIter != fGrid[i].end(); ++reflexIter) {
1507                     TriangulationVertex* reflexVertex = *reflexIter;
1508                     if (reflexVertex->fIndex != ignoreIndex0 &&
1509                         reflexVertex->fIndex != ignoreIndex1 &&
1510                         point_in_triangle(p0, p1, p2, reflexVertex->fPosition)) {
1511                         return true;
1512                     }
1513                 }
1514 
1515             }
1516         }
1517 
1518         return false;
1519     }
1520 
1521 private:
hash(TriangulationVertex * vert) const1522     int hash(TriangulationVertex* vert) const {
1523         int h = (vert->fPosition.fX - fBounds.fLeft)*fGridConversion.fX;
1524         int v = (vert->fPosition.fY - fBounds.fTop)*fGridConversion.fY;
1525         SkASSERT(v*fHCount + h >= 0);
1526         return v*fHCount + h;
1527     }
1528 
1529     SkRect fBounds;
1530     int fHCount;
1531     int fVCount;
1532     int fNumVerts;
1533     // converts distance from the origin to a grid location (when cast to int)
1534     SkVector fGridConversion;
1535     SkTDArray<SkTInternalLList<TriangulationVertex>> fGrid;
1536 };
1537 
1538 // Check to see if a reflex vertex has become a convex vertex after clipping an ear
reclassify_vertex(TriangulationVertex * p,const SkPoint * polygonVerts,int winding,ReflexHash * reflexHash,SkTInternalLList<TriangulationVertex> * convexList)1539 static void reclassify_vertex(TriangulationVertex* p, const SkPoint* polygonVerts,
1540                               int winding, ReflexHash* reflexHash,
1541                               SkTInternalLList<TriangulationVertex>* convexList) {
1542     if (TriangulationVertex::VertexType::kReflex == p->fVertexType) {
1543         SkVector v0 = p->fPosition - polygonVerts[p->fPrevIndex];
1544         SkVector v1 = polygonVerts[p->fNextIndex] - p->fPosition;
1545         if (winding*v0.cross(v1) > SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
1546             p->fVertexType = TriangulationVertex::VertexType::kConvex;
1547             reflexHash->remove(p);
1548             p->fPrev = p->fNext = nullptr;
1549             convexList->addToTail(p);
1550         }
1551     }
1552 }
1553 
SkTriangulateSimplePolygon(const SkPoint * polygonVerts,uint16_t * indexMap,int polygonSize,SkTDArray<uint16_t> * triangleIndices)1554 bool SkTriangulateSimplePolygon(const SkPoint* polygonVerts, uint16_t* indexMap, int polygonSize,
1555                                 SkTDArray<uint16_t>* triangleIndices) {
1556     if (polygonSize < 3) {
1557         return false;
1558     }
1559     // need to be able to represent all the vertices in the 16-bit indices
1560     if (polygonSize >= std::numeric_limits<uint16_t>::max()) {
1561         return false;
1562     }
1563 
1564     // get bounds
1565     SkRect bounds;
1566     if (!bounds.setBoundsCheck(polygonVerts, polygonSize)) {
1567         return false;
1568     }
1569     // get winding direction
1570     // TODO: we do this for all the polygon routines -- might be better to have the client
1571     // compute it and pass it in
1572     int winding = SkGetPolygonWinding(polygonVerts, polygonSize);
1573     if (0 == winding) {
1574         return false;
1575     }
1576 
1577     // Set up vertices
1578     SkAutoSTMalloc<64, TriangulationVertex> triangulationVertices(polygonSize);
1579     int prevIndex = polygonSize - 1;
1580     SkVector v0 = polygonVerts[0] - polygonVerts[prevIndex];
1581     for (int currIndex = 0; currIndex < polygonSize; ++currIndex) {
1582         int nextIndex = (currIndex + 1) % polygonSize;
1583 
1584         SkDEBUGCODE(memset(&triangulationVertices[currIndex], 0, sizeof(TriangulationVertex)));
1585         triangulationVertices[currIndex].fPosition = polygonVerts[currIndex];
1586         triangulationVertices[currIndex].fIndex = currIndex;
1587         triangulationVertices[currIndex].fPrevIndex = prevIndex;
1588         triangulationVertices[currIndex].fNextIndex = nextIndex;
1589         SkVector v1 = polygonVerts[nextIndex] - polygonVerts[currIndex];
1590         if (winding*v0.cross(v1) > SK_ScalarNearlyZero*SK_ScalarNearlyZero) {
1591             triangulationVertices[currIndex].fVertexType = TriangulationVertex::VertexType::kConvex;
1592         } else {
1593             triangulationVertices[currIndex].fVertexType = TriangulationVertex::VertexType::kReflex;
1594         }
1595 
1596         prevIndex = currIndex;
1597         v0 = v1;
1598     }
1599 
1600     // Classify initial vertices into a list of convex vertices and a hash of reflex vertices
1601     // TODO: possibly sort the convexList in some way to get better triangles
1602     SkTInternalLList<TriangulationVertex> convexList;
1603     ReflexHash reflexHash;
1604     if (!reflexHash.init(bounds, polygonSize)) {
1605         return false;
1606     }
1607     prevIndex = polygonSize - 1;
1608     for (int currIndex = 0; currIndex < polygonSize; prevIndex = currIndex, ++currIndex) {
1609         TriangulationVertex::VertexType currType = triangulationVertices[currIndex].fVertexType;
1610         if (TriangulationVertex::VertexType::kConvex == currType) {
1611             int nextIndex = (currIndex + 1) % polygonSize;
1612             TriangulationVertex::VertexType prevType = triangulationVertices[prevIndex].fVertexType;
1613             TriangulationVertex::VertexType nextType = triangulationVertices[nextIndex].fVertexType;
1614             // We prioritize clipping vertices with neighboring reflex vertices.
1615             // The intent here is that it will cull reflex vertices more quickly.
1616             if (TriangulationVertex::VertexType::kReflex == prevType ||
1617                 TriangulationVertex::VertexType::kReflex == nextType) {
1618                 convexList.addToHead(&triangulationVertices[currIndex]);
1619             } else {
1620                 convexList.addToTail(&triangulationVertices[currIndex]);
1621             }
1622         } else {
1623             // We treat near collinear vertices as reflex
1624             reflexHash.add(&triangulationVertices[currIndex]);
1625         }
1626     }
1627 
1628     // The general concept: We are trying to find three neighboring vertices where
1629     // no other vertex lies inside the triangle (an "ear"). If we find one, we clip
1630     // that ear off, and then repeat on the new polygon. Once we get down to three vertices
1631     // we have triangulated the entire polygon.
1632     // In the worst case this is an n^2 algorithm. We can cut down the search space somewhat by
1633     // noting that only convex vertices can be potential ears, and we only need to check whether
1634     // any reflex vertices lie inside the ear.
1635     triangleIndices->setReserve(triangleIndices->count() + 3 * (polygonSize - 2));
1636     int vertexCount = polygonSize;
1637     while (vertexCount > 3) {
1638         bool success = false;
1639         TriangulationVertex* earVertex = nullptr;
1640         TriangulationVertex* p0 = nullptr;
1641         TriangulationVertex* p2 = nullptr;
1642         // find a convex vertex to clip
1643         for (SkTInternalLList<TriangulationVertex>::Iter convexIter = convexList.begin();
1644              convexIter != convexList.end(); ++convexIter) {
1645             earVertex = *convexIter;
1646             SkASSERT(TriangulationVertex::VertexType::kReflex != earVertex->fVertexType);
1647 
1648             p0 = &triangulationVertices[earVertex->fPrevIndex];
1649             p2 = &triangulationVertices[earVertex->fNextIndex];
1650 
1651             // see if any reflex vertices are inside the ear
1652             bool failed = reflexHash.checkTriangle(p0->fPosition, earVertex->fPosition,
1653                                                    p2->fPosition, p0->fIndex, p2->fIndex);
1654             if (failed) {
1655                 continue;
1656             }
1657 
1658             // found one we can clip
1659             success = true;
1660             break;
1661         }
1662         // If we can't find any ears to clip, this probably isn't a simple polygon
1663         if (!success) {
1664             return false;
1665         }
1666 
1667         // add indices
1668         auto indices = triangleIndices->append(3);
1669         indices[0] = indexMap[p0->fIndex];
1670         indices[1] = indexMap[earVertex->fIndex];
1671         indices[2] = indexMap[p2->fIndex];
1672 
1673         // clip the ear
1674         convexList.remove(earVertex);
1675         --vertexCount;
1676 
1677         // reclassify reflex verts
1678         p0->fNextIndex = earVertex->fNextIndex;
1679         reclassify_vertex(p0, polygonVerts, winding, &reflexHash, &convexList);
1680 
1681         p2->fPrevIndex = earVertex->fPrevIndex;
1682         reclassify_vertex(p2, polygonVerts, winding, &reflexHash, &convexList);
1683     }
1684 
1685     // output indices
1686     for (SkTInternalLList<TriangulationVertex>::Iter vertexIter = convexList.begin();
1687          vertexIter != convexList.end(); ++vertexIter) {
1688         TriangulationVertex* vertex = *vertexIter;
1689         *triangleIndices->push() = indexMap[vertex->fIndex];
1690     }
1691 
1692     return true;
1693 }
1694 
1695 ///////////
1696 
crs(SkVector a,SkVector b)1697 static double crs(SkVector a, SkVector b) {
1698     return a.fX * b.fY - a.fY * b.fX;
1699 }
1700 
sign(SkScalar v)1701 static int sign(SkScalar v) {
1702     return v < 0 ? -1 : (v > 0);
1703 }
1704 
1705 struct SignTracker {
1706     int fSign;
1707     int fSignChanges;
1708 
resetSignTracker1709     void reset() {
1710         fSign = 0;
1711         fSignChanges = 0;
1712     }
1713 
initSignTracker1714     void init(int s) {
1715         SkASSERT(fSignChanges == 0);
1716         SkASSERT(s == 1 || s == -1 || s == 0);
1717         fSign = s;
1718         fSignChanges = 1;
1719     }
1720 
updateSignTracker1721     void update(int s) {
1722         if (s) {
1723             if (fSign != s) {
1724                 fSignChanges += 1;
1725                 fSign = s;
1726             }
1727         }
1728     }
1729 };
1730 
1731 struct ConvexTracker {
1732     SkVector    fFirst, fPrev;
1733     SignTracker fDSign, fCSign;
1734     int         fVecCounter;
1735     bool        fIsConcave;
1736 
ConvexTrackerConvexTracker1737     ConvexTracker() { this->reset(); }
1738 
resetConvexTracker1739     void reset() {
1740         fPrev = {0, 0};
1741         fDSign.reset();
1742         fCSign.reset();
1743         fVecCounter = 0;
1744         fIsConcave = false;
1745     }
1746 
addVecConvexTracker1747     void addVec(SkPoint p1, SkPoint p0) {
1748         this->addVec(p1 - p0);
1749     }
addVecConvexTracker1750     void addVec(SkVector v) {
1751         if (v.fX == 0 && v.fY == 0) {
1752             return;
1753         }
1754 
1755         fVecCounter += 1;
1756         if (fVecCounter == 1) {
1757             fFirst = fPrev = v;
1758             fDSign.update(sign(v.fX));
1759             return;
1760         }
1761 
1762         SkScalar d = v.fX;
1763         SkScalar c = crs(fPrev, v);
1764         int sign_c;
1765         if (c) {
1766             sign_c = sign(c);
1767         } else {
1768             if (d >= 0) {
1769                 sign_c = fCSign.fSign;
1770             } else {
1771                 sign_c = -fCSign.fSign;
1772             }
1773         }
1774 
1775         fDSign.update(sign(d));
1776         fCSign.update(sign_c);
1777         fPrev = v;
1778 
1779         if (fDSign.fSignChanges > 3 || fCSign.fSignChanges > 1) {
1780             fIsConcave = true;
1781         }
1782     }
1783 
finalCrossConvexTracker1784     void finalCross() {
1785         this->addVec(fFirst);
1786     }
1787 };
1788 
SkIsPolyConvex_experimental(const SkPoint pts[],int count)1789 bool SkIsPolyConvex_experimental(const SkPoint pts[], int count) {
1790     if (count <= 3) {
1791         return true;
1792     }
1793 
1794     ConvexTracker tracker;
1795 
1796     for (int i = 0; i < count - 1; ++i) {
1797         tracker.addVec(pts[i + 1], pts[i]);
1798         if (tracker.fIsConcave) {
1799             return false;
1800         }
1801     }
1802     tracker.addVec(pts[0], pts[count - 1]);
1803     tracker.finalCross();
1804     return !tracker.fIsConcave;
1805 }
1806 
1807