1
2/*
3 * Copyright 2009 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11////////////////////////////////////////////////////////////////////////////////
12// This is an implementation of the triangulation algorithm described by Alain
13// Fournier and Delfin Montuno, in "Triangulating Simple Polygons and Equivalent
14// Problems", in the ACM Transactions on Graphics, vol. 3, no. 2, April 1984,
15// pp. 153-174.
16//
17// No new vertices are created in the triangulation: triangles are constructed
18// only from the points in the original polygon, so there is no possibility for
19// cracks to develop from finite precision arithmetic.
20////////////////////////////////////////////////////////////////////////////////
21
22// TODO:
23// - RemoveDegenerateTrapezoids() was added to make the code robust, but it
24//   unfortunately introduces T-vertices. Make it robust without T-vertices.
25// - It should be easy enough to detect whether the outer contour is right- or
26//   left-handed by looking at the top vertex, which is available in the
27//   pre-sort during trapezoidization. Use this information in angleIsConvex()
28//   to allowed either handedness outer contour. In either case, though, holes
29//   need to have the opposite orientation.
30// - SkTHeapSort was broken, so I wrote a bubble sort so that I could make other
31//   things work. Use SkQSort() instead.
32// - The ActiveTrapezoid array does a linear search which is O(n) inefficient.
33//   Use SkSearch to implement O(log n) binary search and insertion sort.
34// - There is no need to use SkTDArray for everything. Use SkAutoTMalloc for
35//   everything else.
36
37#include "SkTDArray.h"
38#include "SkGeometry.h"
39#include "SkTSort.h"
40
41// This is used to prevent runaway code bugs, and can probably be removed after
42// the code has been proven robust.
43#define kMaxCount 1000
44
45#define DEBUG
46#ifdef DEBUG
47//------------------------------------------------------------------------------
48// Debugging support
49//------------------------------------------------------------------------------
50
51#include <cstdio>
52#include <stdarg.h>
53
54static int gDebugLevel = 0;   // This enables debug reporting.
55
56static void DebugPrintf(const char *format, ...) {
57    if (gDebugLevel > 0) {
58        va_list ap;
59        va_start(ap, format);
60        vprintf(format, ap);
61        va_end(ap);
62    }
63}
64
65static void FailureMessage(const char *format, ...) {
66    if (1) {
67        printf("FAILURE: ");
68        va_list ap;
69        va_start(ap, format);
70        vprintf(format, ap);
71        va_end(ap);
72    }
73}
74#else  // !DEBUG
75inline void DebugPrintf(const char *format, ...) {}
76inline void FailureMessage(const char *format, ...) {}
77#endif  // DEBUG
78
79
80// Forward declaration.
81class Vertex;
82
83
84//------------------------------------------------------------------------------
85// The Trapezoid (actually, up to two of them) is embedded into a Vertex, whose
86// point() provides the top of the Trapezoid, whereas the bottom, and the left
87// and right edges, are stored in the Trapezoid. The edges are represented by
88// their tail point; the head is the successive point modulo the number of
89// points in the polygon. Only the Y coordinate of the top and bottom are
90// relevant.
91//------------------------------------------------------------------------------
92class Trapezoid {
93public:
94    const Vertex* left()   const    { return fLeft;   }
95    const Vertex* right()  const    { return fRight;  }
96    const Vertex* bottom() const    { return fBottom; }
97    Vertex* left()                  { return fLeft;   }
98    Vertex* right()                 { return fRight;  }
99    Vertex* bottom()                { return fBottom; }
100    void   setLeft(Vertex *left)    { fLeft   = left;   }
101    void  setRight(Vertex *right)   { fRight  = right;  }
102    void setBottom(Vertex *bottom)  { fBottom = bottom; }
103    void nullify()                  { setBottom(NULL); }
104
105    bool operator<(Trapezoid &t1)   { return compare(t1) < 0; }
106    bool operator>(Trapezoid &t1)   { return compare(t1) > 0; }
107
108private:
109    Vertex *fLeft, *fRight, *fBottom;
110
111    // These return a number that is less than, equal to, or greater than zero
112    // depending on whether the trapezoid or point is to the left, on, or to the
113    // right.
114    SkScalar compare(const Trapezoid &t1) const;
115    SkScalar compare(const SkPoint &p) const;
116};
117
118
119//------------------------------------------------------------------------------
120// The ActiveTrapezoids are a sorted list containing the currently active
121// trapezoids, i.e. those that have the top, left, and right, but still need the
122// bottom. This could use some optimization, to reduce search time from O(n) to
123// O(log n).
124//------------------------------------------------------------------------------
125class ActiveTrapezoids {
126public:
127    ActiveTrapezoids() { fTrapezoids.setCount(0); }
128
129    size_t count() const { return fTrapezoids.count(); }
130
131    // Select an unused trapezoid from the Vertex vt, initialize it with the
132    // left and right edges, and insert it into the sorted list.
133    bool insertNewTrapezoid(Vertex *vt, Vertex *left, Vertex *right);
134
135    // Remove the specified Trapezoids from the active list.
136    void remove(Trapezoid *t);
137
138    // Determine whether the given point lies within any active trapezoid, and
139    // return a pointer to that Trapezoid.
140    bool withinActiveTrapezoid(const SkPoint &pt, Trapezoid **tp);
141
142    // Find an active trapezoid that contains the given edge.
143    Trapezoid* getTrapezoidWithEdge(const Vertex *edge);
144
145private:
146    // Insert the specified Trapezoid into the sorted list.
147    void insert(Trapezoid *t);
148
149    // The sorted list of active trapezoids. This is O(n), and would benefit
150    // a 2-3 tree o achieve O(log n).
151    SkTDArray<Trapezoid*> fTrapezoids;  // Fournier suggests a 2-3 tree instead.
152};
153
154
155//------------------------------------------------------------------------------
156// The Vertex is used to communicate information between the various phases of
157// triangulation.
158//------------------------------------------------------------------------------
159class Vertex {
160public:
161    enum VertexType { MONOTONE, CONVEX, CONCAVE };
162
163    Trapezoid fTrap0;
164    Trapezoid fTrap1;
165
166    const SkPoint &point() const        { return fPoint; }
167    void setPoint(const SkPoint &point) { fPoint = point; }
168
169    // The next and previous vertices around the polygon.
170    Vertex *next()                      { return fNext; }
171    Vertex *prev()                      { return fPrev; }
172    const Vertex *next() const          { return fNext; }
173    const Vertex *prev() const          { return fPrev; }
174    void setNext(Vertex *next)          { fNext = next; }
175    void setPrev(Vertex *prev)          { fPrev = prev; }
176
177    void setDone(bool done)             { fDone = done; }
178    bool done() const                   { return fDone; }
179
180    // Trapezoid accessors return non-null for any complete trapezoids.
181    void trapezoids(Trapezoid **trap0, Trapezoid **trap1) {
182        *trap0 = (fTrap0.bottom() != NULL) ? &fTrap0 : NULL;
183        *trap1 = (fTrap1.bottom() != NULL) ? &fTrap1 : NULL;
184    }
185
186    // Eliminate a trapezoid.
187    void nullifyTrapezoid() {
188        if (fTrap1.bottom() != NULL) {
189            DebugPrintf("Unexpected non-null second trapezoid.\n");
190            fTrap1.nullify();
191            return;
192        }
193        fTrap0.nullify();
194    }
195
196    // Determine whether the edge specified by this Vertex shares the given top
197    // and bottom.
198    bool shareEdge(Vertex *top, Vertex *bottom);
199
200    // Determines whether the angle specified by { prev, this, next } is convex.
201    // Note that collinear is considered to be convex.
202    bool angleIsConvex();
203
204    // Remove this Vertex from the { prev, next } linked list.
205    void delink() {
206        Vertex *p = prev(),
207               *n = next();
208        p->setNext(n);
209        n->setPrev(p);
210    }
211
212    // Return a number that is less than, equal to, or greater than zero
213    // depending on whether the point is to the left, on, or to the right of the
214    // edge that has this Vertex as a base.
215    SkScalar compare(const SkPoint &pt) const;
216
217    // Classify the vertex, and return its sorted edges.
218    VertexType classify(Vertex **e0, Vertex **e1);
219
220    // This helps determine unimonotonicity.
221    Vertex *diagonal();
222
223private:
224    SkPoint fPoint;
225    Vertex *fNext;
226    Vertex *fPrev;
227    bool fDone;
228};
229
230
231bool Vertex::angleIsConvex() {
232    SkPoint vPrev = prev()->point() - point(),
233            vNext = next()->point() - point();
234    // TODO(turk): There might be overflow in fixed-point.
235    return SkPoint::CrossProduct(vNext, vPrev) >= 0;
236}
237
238
239bool Vertex::shareEdge(Vertex *top, Vertex *bottom) {
240    return (((this == top)    && (this->next() == bottom)) ||
241            ((this == bottom) && (this->next() == top)));
242}
243
244
245SkScalar Vertex::compare(const SkPoint &pt) const  {
246    SkPoint ve = next()->point() - point(),
247            vp = pt              - point();
248    SkScalar d;
249    if (ve.fY == 0) {
250        // Return twice the distance to the center of the horizontal edge.
251        d = ve.fX + pt.fX - next()->point().fX;
252    } else {
253        // Return the distance to the edge, scaled by the edge length.
254        d = SkPoint::CrossProduct(ve, vp);
255        if (ve.fY > 0) d = -d;
256    }
257    return d;
258}
259
260
261SkScalar Trapezoid::compare(const SkPoint &pt) const {
262    SkScalar d = left()->compare(pt);
263    if (d <= 0)
264        return d;   // Left of the left edge.
265    d = right()->compare(pt);
266    if (d >= 0)
267        return d;   // Right of the right edge.
268    return 0;       // Somewhere between the left and the right edges.
269}
270
271
272
273SkScalar Trapezoid::compare(const Trapezoid &t1) const {
274#if 1
275    SkScalar d = left()->compare(t1.left()->point());
276    if (d == 0)
277        d = right()->compare(t1.right()->point());
278    return d;
279#else
280    SkScalar dl =  left()->compare( t1.left()->point()),
281             dr = right()->compare(t1.right()->point());
282    if (dl < 0 && dr < 0)
283        return dr;
284    if (dl > 0 && dr > 0)
285        return dl;
286    return 0;
287#endif
288}
289
290
291Trapezoid* ActiveTrapezoids::getTrapezoidWithEdge(const Vertex *edge) {
292    DebugPrintf("Entering getTrapezoidWithEdge(): looking through %d\n",
293           fTrapezoids.count());
294    DebugPrintf("trying to find %p: ", edge);
295    Trapezoid **tp;
296    for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
297        SkASSERT(tp != NULL);
298        SkASSERT(*tp != NULL);
299        DebugPrintf("%p and %p, ", (**tp).left(), (**tp).right());
300        if ((**tp).left() == edge || (**tp).right() == edge) {
301            DebugPrintf("\ngetTrapezoidWithEdge found the trapezoid\n");
302            return *tp;
303        }
304    }
305    DebugPrintf("getTrapezoidWithEdge found no trapezoid\n");
306    return NULL;
307}
308
309
310bool ActiveTrapezoids::insertNewTrapezoid(Vertex *vt,
311                                          Vertex *left,
312                                          Vertex *right) {
313    DebugPrintf("Inserting a trapezoid...");
314    if (vt->fTrap0.left() == NULL && vt->fTrap0.right() == NULL) {
315        vt->fTrap0.setLeft(left);
316        vt->fTrap0.setRight(right);
317        insert(&vt->fTrap0);
318    } else if (vt->fTrap1.left() == NULL && vt->fTrap1.right() == NULL) {
319        DebugPrintf("a second one...");
320        vt->fTrap1.setLeft(left);
321        vt->fTrap1.setRight(right);
322        if (vt->fTrap1 < vt->fTrap0) {  // Keep trapezoids sorted.
323            remove(&vt->fTrap0);
324            Trapezoid t = vt->fTrap0;
325            vt->fTrap0 = vt->fTrap1;
326            vt->fTrap1 = t;
327            insert(&vt->fTrap0);
328        }
329        insert(&vt->fTrap1);
330    } else {
331        FailureMessage("More than 2 trapezoids requested for a vertex\n");
332        return false;
333    }
334    DebugPrintf(" done. %d incomplete trapezoids\n", fTrapezoids.count());
335    return true;
336}
337
338
339void ActiveTrapezoids::insert(Trapezoid *t) {
340    Trapezoid **tp;
341    for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp)
342        if (**tp > *t)
343            break;
344    fTrapezoids.insert(tp - fTrapezoids.begin(), 1, &t);
345    // SHOULD VERIFY THAT ALL TRAPEZOIDS ARE PROPERLY SORTED
346}
347
348
349void ActiveTrapezoids::remove(Trapezoid *t) {
350    DebugPrintf("Removing a trapezoid...");
351    for (Trapezoid **tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
352        if (*tp == t) {
353            fTrapezoids.remove(tp - fTrapezoids.begin());
354            DebugPrintf(" done.\n");
355            return;
356        }
357    }
358    DebugPrintf(" Arghh! Panic!\n");
359    SkASSERT(t == 0);   // Cannot find t in active trapezoid list.
360}
361
362
363bool ActiveTrapezoids::withinActiveTrapezoid(const SkPoint &pt,
364                                             Trapezoid **trap) {
365    DebugPrintf("Entering withinActiveTrapezoid()\n");
366    // This is where a good search data structure would be helpful.
367    Trapezoid **t;
368    for (t = fTrapezoids.begin(); t < fTrapezoids.end(); ++t) {
369        if ((**t).left()->compare(pt) <= 0) {
370            // The point is to the left of the left edge of this trapezoid.
371            DebugPrintf("withinActiveTrapezoid: Before a trapezoid\n");
372            *trap = *t;     // Return the place where a new trapezoid would go.
373// We have a bug with the sorting -- look through everything.
374            continue;
375//             return false;   // Outside all trapezoids, since they are sorted.
376        }
377        // The point is to the right of the left edge of this trapezoid.
378
379        if ((**t).right()->compare(pt) < 0) {
380            // The point is to the left of the right edge.
381            DebugPrintf("withinActiveTrapezoid: Within an Active Trapezoid\n");
382            *trap = *t;
383            return true;
384        }
385    }
386
387    // The point is to the right of all trapezoids.
388    DebugPrintf("withinActiveTrapezoid: After all trapezoids\n");
389    *trap = NULL;
390    return false;
391}
392
393
394Vertex* Vertex::diagonal() {
395    Vertex *diag = NULL;
396    if (fTrap0.bottom() != NULL) {
397        if (!fTrap0.left() ->shareEdge(this, fTrap0.bottom()) &&
398            !fTrap0.right()->shareEdge(this, fTrap0.bottom())
399        ) {
400            diag = fTrap0.bottom();
401            fTrap0 = fTrap1;
402            fTrap1.nullify();
403        } else if (fTrap1.bottom() != NULL &&
404                  !fTrap1.left() ->shareEdge(this, fTrap1.bottom()) &&
405                  !fTrap1.right()->shareEdge(this, fTrap1.bottom())
406        ) {
407            diag = fTrap1.bottom();
408            fTrap1.nullify();
409        }
410    }
411    return diag;
412}
413
414
415// We use this to sort the edges vertically for a scan-conversion type of
416// operation.
417class VertexPtr {
418public:
419    Vertex *vt;
420};
421
422
423bool operator<(VertexPtr &v0, VertexPtr &v1) {
424    // DebugPrintf("< %p %p\n", &v0, &v1);
425    if (v0.vt->point().fY < v1.vt->point().fY)  return true;
426    if (v0.vt->point().fY > v1.vt->point().fY)  return false;
427    if (v0.vt->point().fX < v1.vt->point().fX)  return true;
428    else                                        return false;
429}
430
431
432bool operator>(VertexPtr &v0, VertexPtr &v1) {
433    // DebugPrintf("> %p %p\n", &v0, &v1);
434    if (v0.vt->point().fY > v1.vt->point().fY)  return true;
435    if (v0.vt->point().fY < v1.vt->point().fY)  return false;
436    if (v0.vt->point().fX > v1.vt->point().fX)  return true;
437    else                                        return false;
438}
439
440
441static void SetVertexPoints(size_t numPts, const SkPoint *pt, Vertex *vt) {
442    for (; numPts-- != 0; ++pt, ++vt)
443        vt->setPoint(*pt);
444}
445
446
447static void InitializeVertexTopology(size_t numPts, Vertex *v1) {
448    Vertex *v0 = v1 + numPts - 1, *v_1 = v0 - 1;
449    for (; numPts-- != 0; v_1 = v0, v0 = v1++) {
450        v0->setPrev(v_1);
451        v0->setNext(v1);
452    }
453}
454
455Vertex::VertexType Vertex::classify(Vertex **e0, Vertex **e1) {
456    VertexType type;
457    SkPoint vPrev, vNext;
458    vPrev.fX = prev()->point().fX - point().fX;
459    vPrev.fY = prev()->point().fY - point().fY;
460    vNext.fX = next()->point().fX - point().fX;
461    vNext.fY = next()->point().fY - point().fY;
462
463    // This can probably be simplified, but there are enough potential bugs,
464    // we will leave it expanded until all cases are tested appropriately.
465    if (vPrev.fY < 0) {
466        if (vNext.fY > 0) {
467            // Prev comes from above, Next goes below.
468            type = MONOTONE;
469            *e0 = prev();
470            *e1 = this;
471        } else if (vNext.fY < 0) {
472            // The are both above: sort so that e0 is on the left.
473            type = CONCAVE;
474            if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
475                *e0 = this;
476                *e1 = prev();
477            } else {
478                *e0 = prev();
479                *e1 = this;
480            }
481        } else {
482            DebugPrintf("### py < 0, ny = 0\n");
483            if (vNext.fX < 0) {
484                type = CONCAVE;
485                *e0 = this;     // flat to the left
486                *e1 = prev();   // concave on the right
487            } else {
488                type = CONCAVE;
489                *e0 = prev();   // concave to the left
490                *e1 = this;     // flat to the right
491            }
492        }
493    } else if (vPrev.fY > 0) {
494        if (vNext.fY < 0) {
495            // Next comes from above, Prev goes below.
496            type = MONOTONE;
497            *e0 = this;
498            *e1 = prev();
499        } else if (vNext.fY > 0) {
500            // They are both below: sort so that e0 is on the left.
501            type = CONVEX;
502            if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
503                *e0 = prev();
504                *e1 = this;
505            } else {
506                *e0 = this;
507                *e1 = prev();
508            }
509        } else {
510            DebugPrintf("### py > 0, ny = 0\n");
511            if (vNext.fX < 0) {
512                type = MONOTONE;
513                *e0 = this;     // flat to the left
514                *e1 = prev();   // convex on the right - try monotone first
515            } else {
516                type = MONOTONE;
517                *e0 = prev();   // convex to the left - try monotone first
518                *e1 = this;     // flat to the right
519            }
520        }
521    } else {  // vPrev.fY == 0
522        if (vNext.fY < 0) {
523            DebugPrintf("### py = 0, ny < 0\n");
524            if (vPrev.fX < 0) {
525                type = CONCAVE;
526                *e0 = prev();   // flat to the left
527                *e1 = this;     // concave on the right
528            } else {
529                type = CONCAVE;
530                *e0 = this;     // concave on the left - defer
531                *e1 = prev();   // flat to the right
532            }
533        } else if (vNext.fY > 0) {
534            DebugPrintf("### py = 0, ny > 0\n");
535            if (vPrev.fX < 0) {
536                type = MONOTONE;
537                *e0 = prev();   // flat to the left
538                *e1 = this;     // convex on the right - try monotone first
539            } else {
540                type = MONOTONE;
541                *e0 = this;     // convex to the left - try monotone first
542                *e1 = prev();   // flat to the right
543            }
544        } else {
545            DebugPrintf("### py = 0, ny = 0\n");
546            // First we try concave, then monotone, then convex.
547            if (vPrev.fX <= vNext.fX) {
548                type = CONCAVE;
549                *e0 = prev();   // flat to the left
550                *e1 = this;     // flat to the right
551            } else {
552                type = CONCAVE;
553                *e0 = this;     // flat to the left
554                *e1 = prev();   // flat to the right
555            }
556        }
557    }
558    return type;
559}
560
561
562#ifdef DEBUG
563static const char* GetVertexTypeString(Vertex::VertexType type) {
564    const char *typeStr = NULL;
565    switch (type) {
566        case Vertex::MONOTONE:
567            typeStr = "MONOTONE";
568            break;
569        case Vertex::CONCAVE:
570            typeStr = "CONCAVE";
571            break;
572        case Vertex::CONVEX:
573            typeStr = "CONVEX";
574            break;
575    }
576    return typeStr;
577}
578
579
580static void PrintVertices(size_t numPts, Vertex *vt) {
581    DebugPrintf("\nVertices:\n");
582    for (size_t i = 0; i < numPts; i++) {
583        Vertex *e0, *e1;
584        Vertex::VertexType type = vt[i].classify(&e0, &e1);
585        DebugPrintf("%2d: (%.7g, %.7g), prev(%d), next(%d), "
586                    "type(%s), left(%d), right(%d)",
587                    i, vt[i].point().fX, vt[i].point().fY,
588                    vt[i].prev() - vt, vt[i].next() - vt,
589                    GetVertexTypeString(type), e0 - vt, e1 - vt);
590        Trapezoid *trap[2];
591        vt[i].trapezoids(trap, trap+1);
592        for (int j = 0; j < 2; ++j) {
593            if (trap[j] != NULL) {
594                DebugPrintf(", trap(L=%d, R=%d, B=%d)",
595                            trap[j]->left()   - vt,
596                            trap[j]->right()  - vt,
597                            trap[j]->bottom() - vt);
598            }
599        }
600        DebugPrintf("\n");
601    }
602}
603
604
605static void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {
606    DebugPrintf("\nSorted Vertices:\n");
607    for (size_t i = 0; i < numPts; i++) {
608        Vertex *e0, *e1;
609        Vertex *vt = vp[i].vt;
610        Vertex::VertexType type = vt->classify(&e0, &e1);
611        DebugPrintf("%2d: %2d: (%.7g, %.7g), prev(%d), next(%d), "
612                    "type(%s), left(%d), right(%d)",
613                    i, vt - vtBase, vt->point().fX, vt->point().fY,
614                    vt->prev() - vtBase, vt->next() - vtBase,
615                    GetVertexTypeString(type), e0 - vtBase, e1 - vtBase);
616        Trapezoid *trap[2];
617        vt->trapezoids(trap, trap+1);
618        for (int j = 0; j < 2; ++j) {
619            if (trap[j] != NULL) {
620                DebugPrintf(", trap(L=%d, R=%d, B=%d)",
621                            trap[j]->left()   - vtBase,
622                            trap[j]->right()  - vtBase,
623                            trap[j]->bottom() - vtBase);
624            }
625        }
626        DebugPrintf("\n");
627    }
628}
629#else  // !DEBUG
630inline void PrintVertices(size_t numPts, Vertex *vt) {}
631inline void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {}
632#endif  // !DEBUG
633
634
635// SkTHeapSort is broken, so we use a bubble sort in the meantime.
636template <typename T>
637void BubbleSort(T *array, size_t count) {
638    bool sorted;
639    size_t count_1 = count - 1;
640    do {
641        sorted = true;
642        for (size_t i = 0; i < count_1; ++i) {
643            if (array[i + 1] < array[i]) {
644                T t = array[i];
645                array[i] = array[i + 1];
646                array[i + 1] = t;
647                sorted = false;
648            }
649        }
650    } while (!sorted);
651}
652
653
654// Remove zero-height trapezoids.
655static void RemoveDegenerateTrapezoids(size_t numVt, Vertex *vt) {
656    for (; numVt-- != 0; vt++) {
657        Trapezoid *traps[2];
658        vt->trapezoids(traps, traps+1);
659        if (traps[1] != NULL &&
660                vt->point().fY >= traps[1]->bottom()->point().fY) {
661            traps[1]->nullify();
662            traps[1] = NULL;
663        }
664        if (traps[0] != NULL &&
665                vt->point().fY >= traps[0]->bottom()->point().fY) {
666            if (traps[1] != NULL) {
667                *traps[0] = *traps[1];
668                traps[1]->nullify();
669            } else {
670                traps[0]->nullify();
671            }
672        }
673    }
674}
675
676
677// Enhance the polygon with trapezoids.
678bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) {
679    DebugPrintf("ConvertPointsToVertices()\n");
680
681    // Clear everything.
682    DebugPrintf("Zeroing vertices\n");
683    sk_bzero(vta, numPts * sizeof(*vta));
684
685    // Initialize vertices.
686    DebugPrintf("Initializing vertices\n");
687    SetVertexPoints(numPts, pts, vta);
688    InitializeVertexTopology(numPts, vta);
689
690    PrintVertices(numPts, vta);
691
692    SkTDArray<VertexPtr> vtptr;
693    vtptr.setCount(numPts);
694    for (int i = numPts; i-- != 0;)
695        vtptr[i].vt = vta + i;
696    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
697    DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(),
698        &vtptr[0], &vtptr[vtptr.count() - 1]
699    );
700//  SkTHeapSort(vtptr.begin(), vtptr.count());
701    BubbleSort(vtptr.begin(), vtptr.count());
702    DebugPrintf("Done sorting\n");
703    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
704
705    DebugPrintf("Traversing sorted vertrap ptrs\n");
706    ActiveTrapezoids incompleteTrapezoids;
707    for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) {
708        DebugPrintf("%d: sorted vertrap %d\n",
709                    vtpp - vtptr.begin(), vtpp->vt - vta);
710        Vertex *vt = vtpp->vt;
711        Vertex *e0, *e1;
712        Trapezoid *t;
713        switch (vt->classify(&e0, &e1)) {
714            case Vertex::MONOTONE:
715            monotone:
716                DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta);
717                // We should find one edge.
718                t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
719                if (t == NULL) {      // One of the edges is flat.
720                    DebugPrintf("Monotone: cannot find a trapezoid with e0: "
721                                "trying convex\n");
722                    goto convex;
723                }
724                t->setBottom(vt);     // This trapezoid is now complete.
725                incompleteTrapezoids.remove(t);
726
727                if (e0 == t->left())  // Replace the left edge.
728                    incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
729                else                  // Replace the right edge.
730                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1);
731                break;
732
733            case Vertex::CONVEX:      // Start of a new trapezoid.
734            convex:
735                // We don't expect to find any edges.
736                DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta);
737                if (incompleteTrapezoids.withinActiveTrapezoid(
738                        vt->point(), &t)) {
739                    // Complete trapezoid.
740                    SkASSERT(t != NULL);
741                    t->setBottom(vt);
742                    incompleteTrapezoids.remove(t);
743                    // Introduce two new trapezoids.
744                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0);
745                    incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
746                } else {
747                    // Insert a new trapezoid.
748                    incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1);
749                }
750                break;
751
752            case Vertex::CONCAVE:   // End of a trapezoid.
753                DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta);
754                // We should find two edges.
755                t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
756                if (t == NULL) {
757                    DebugPrintf("Concave: cannot find a trapezoid with e0: "
758                                " trying monotone\n");
759                    goto monotone;
760                }
761                SkASSERT(t != NULL);
762                if (e0 == t->left() && e1 == t->right()) {
763                    DebugPrintf(
764                            "Concave edges belong to the same trapezoid.\n");
765                    // Edges belong to the same trapezoid.
766                    // Complete trapezoid & transfer it from the active list.
767                    t->setBottom(vt);
768                    incompleteTrapezoids.remove(t);
769                } else {  // Edges belong to different trapezoids
770                    DebugPrintf(
771                            "Concave edges belong to different trapezoids.\n");
772                    // Complete left and right trapezoids.
773                    Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge(
774                                                                            e1);
775                    if (s == NULL) {
776                        DebugPrintf(
777                                "Concave: cannot find a trapezoid with e1: "
778                                " trying monotone\n");
779                        goto monotone;
780                    }
781                    t->setBottom(vt);
782                    s->setBottom(vt);
783                    incompleteTrapezoids.remove(t);
784                    incompleteTrapezoids.remove(s);
785
786                    // Merge the two trapezoids into one below this vertex.
787                    incompleteTrapezoids.insertNewTrapezoid(vt, t->left(),
788                                                                s->right());
789                }
790                break;
791        }
792    }
793
794    RemoveDegenerateTrapezoids(numPts, vta);
795
796    DebugPrintf("Done making trapezoids\n");
797    PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
798
799    size_t k = incompleteTrapezoids.count();
800    if (k > 0) {
801        FailureMessage("%d incomplete trapezoids\n", k);
802        return false;
803    }
804    return true;
805}
806
807
808inline void appendTriangleAtVertex(const Vertex *v,
809                                   SkTDArray<SkPoint> *triangles) {
810    SkPoint *p = triangles->append(3);
811    p[0] = v->prev()->point();
812    p[1] = v->point();
813    p[2] = v->next()->point();
814    DebugPrintf(
815          "Appending triangle: { (%.7g, %.7g), (%.7g, %.7g), (%.7g, %.7g) }\n",
816          p[0].fX, p[0].fY,
817          p[1].fX, p[1].fY,
818          p[2].fX, p[2].fY
819    );
820}
821
822
823static size_t CountVertices(const Vertex *first, const Vertex *last) {
824    DebugPrintf("Counting vertices: ");
825    size_t count = 1;
826    for (; first != last; first = first->next()) {
827        ++count;
828        SkASSERT(count <= kMaxCount);
829        if (count >= kMaxCount) {
830            FailureMessage("Vertices do not seem to be in a linked chain\n");
831            break;
832        }
833    }
834    return count;
835}
836
837
838bool operator<(const SkPoint &p0, const SkPoint &p1) {
839    if (p0.fY < p1.fY)  return true;
840    if (p0.fY > p1.fY)  return false;
841    if (p0.fX < p1.fX)  return true;
842    else                return false;
843}
844
845
846static void PrintLinkedVertices(size_t n, Vertex *vertices) {
847    DebugPrintf("%d vertices:\n", n);
848    Vertex *v;
849    for (v = vertices; n-- != 0; v = v->next())
850        DebugPrintf("   (%.7g, %.7g)\n", v->point().fX, v->point().fY);
851    if (v != vertices)
852        FailureMessage("Vertices are not in a linked chain\n");
853}
854
855
856// Triangulate an unimonotone chain.
857bool TriangulateMonotone(Vertex *first, Vertex *last,
858                         SkTDArray<SkPoint> *triangles) {
859    DebugPrintf("TriangulateMonotone()\n");
860
861    size_t numVertices = CountVertices(first, last);
862    if (numVertices == kMaxCount) {
863        FailureMessage("Way too many vertices: %d:\n", numVertices);
864        PrintLinkedVertices(numVertices, first);
865        return false;
866    }
867
868    Vertex *start = first;
869    // First find the point with the smallest Y.
870    DebugPrintf("TriangulateMonotone: finding bottom\n");
871    int count = kMaxCount;    // Maximum number of vertices.
872    for (Vertex *v = first->next(); v != first && count-- > 0; v = v->next())
873        if (v->point() < start->point())
874            start = v;
875    if (count <= 0) {
876        FailureMessage("TriangulateMonotone() was given disjoint chain\n");
877        return false;   // Something went wrong.
878    }
879
880    // Start at the far end of the long edge.
881    if (start->prev()->point() < start->next()->point())
882        start = start->next();
883
884    Vertex *current = start->next();
885    while (numVertices >= 3) {
886        if (current->angleIsConvex()) {
887            DebugPrintf("Angle %p is convex\n", current);
888            // Print the vertices
889            PrintLinkedVertices(numVertices, start);
890
891            appendTriangleAtVertex(current, triangles);
892            if (triangles->count() > kMaxCount * 3) {
893                FailureMessage("An extraordinarily large number of triangles "
894                               "were generated\n");
895                return false;
896            }
897            Vertex *save = current->prev();
898            current->delink();
899            current = (save == start || save == start->prev()) ? start->next()
900                                                               : save;
901            --numVertices;
902        } else {
903            if (numVertices == 3) {
904                FailureMessage("Convexity error in TriangulateMonotone()\n");
905                appendTriangleAtVertex(current, triangles);
906                return false;
907            }
908            DebugPrintf("Angle %p is concave\n", current);
909            current = current->next();
910        }
911    }
912    return true;
913}
914
915
916// Split the polygon into sets of unimonotone chains, and eventually call
917// TriangulateMonotone() to convert them into triangles.
918bool Triangulate(Vertex *first, Vertex *last, SkTDArray<SkPoint> *triangles) {
919    DebugPrintf("Triangulate()\n");
920    Vertex *currentVertex = first;
921    while (!currentVertex->done()) {
922        currentVertex->setDone(true);
923        Vertex *bottomVertex = currentVertex->diagonal();
924        if (bottomVertex != NULL) {
925            Vertex *saveNext = currentVertex->next();
926            Vertex *savePrev = bottomVertex->prev();
927            currentVertex->setNext(bottomVertex);
928            bottomVertex->setPrev(currentVertex);
929            currentVertex->nullifyTrapezoid();
930            bool success = Triangulate(bottomVertex, currentVertex, triangles);
931            currentVertex->setDone(false);
932            bottomVertex->setDone(false);
933            currentVertex->setNext(saveNext);
934            bottomVertex->setPrev(savePrev);
935            bottomVertex->setNext(currentVertex);
936            currentVertex->setPrev(bottomVertex);
937            return Triangulate(currentVertex, bottomVertex, triangles)
938                   && success;
939        } else {
940            currentVertex = currentVertex->next();
941        }
942    }
943    return TriangulateMonotone(first, last, triangles);
944}
945
946
947bool SkConcaveToTriangles(size_t numPts,
948                          const SkPoint pts[],
949                          SkTDArray<SkPoint> *triangles) {
950    DebugPrintf("SkConcaveToTriangles()\n");
951
952    SkTDArray<Vertex> vertices;
953    vertices.setCount(numPts);
954    if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
955        return false;
956
957    triangles->setReserve(numPts);
958    triangles->setCount(0);
959    return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
960}
961