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