LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkConcaveToTriangles.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 490 0 0.0 %
Date: 2012-06-02 Functions: 58 0 0.0 %

       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                 : 
      54                 : static int gDebugLevel = 0;   // This enables debug reporting.
      55                 : 
      56               0 : static void DebugPrintf(const char *format, ...) {
      57               0 :     if (gDebugLevel > 0) {
      58                 :         va_list ap;
      59               0 :         va_start(ap, format);
      60               0 :         vprintf(format, ap);
      61               0 :         va_end(ap);
      62                 :     }
      63               0 : }
      64                 : 
      65               0 : static void FailureMessage(const char *format, ...) {
      66                 :     if (1) {
      67               0 :         printf("FAILURE: ");
      68                 :         va_list ap;
      69               0 :         va_start(ap, format);
      70               0 :         vprintf(format, ap);
      71               0 :         va_end(ap);
      72                 :     }
      73               0 : }
      74                 : #else  // !DEBUG
      75                 : inline void DebugPrintf(const char *format, ...) {}
      76                 : inline void FailureMessage(const char *format, ...) {}
      77                 : #endif  // DEBUG
      78                 : 
      79                 : 
      80                 : // Forward declaration.
      81                 : class 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                 : //------------------------------------------------------------------------------
      92                 : class Trapezoid {
      93                 : public:
      94               0 :     const Vertex* left()   const    { return fLeft;   }
      95               0 :     const Vertex* right()  const    { return fRight;  }
      96                 :     const Vertex* bottom() const    { return fBottom; }
      97               0 :     Vertex* left()                  { return fLeft;   }
      98               0 :     Vertex* right()                 { return fRight;  }
      99               0 :     Vertex* bottom()                { return fBottom; }
     100               0 :     void   setLeft(Vertex *left)    { fLeft   = left;   }
     101               0 :     void  setRight(Vertex *right)   { fRight  = right;  }
     102               0 :     void setBottom(Vertex *bottom)  { fBottom = bottom; }
     103               0 :     void nullify()                  { setBottom(NULL); }
     104                 : 
     105               0 :     bool operator<(Trapezoid &t1)   { return compare(t1) < 0; }
     106               0 :     bool operator>(Trapezoid &t1)   { return compare(t1) > 0; }
     107                 : 
     108                 : private:
     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                 : //------------------------------------------------------------------------------
     125               0 : class ActiveTrapezoids {
     126                 : public:
     127               0 :     ActiveTrapezoids() { fTrapezoids.setCount(0); }
     128                 : 
     129               0 :     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                 : 
     145                 : private:
     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                 : //------------------------------------------------------------------------------
     159                 : class Vertex {
     160                 : public:
     161                 :     enum VertexType { MONOTONE, CONVEX, CONCAVE };
     162                 : 
     163                 :     Trapezoid fTrap0;
     164                 :     Trapezoid fTrap1;
     165                 : 
     166               0 :     const SkPoint &point() const        { return fPoint; }
     167               0 :     void setPoint(const SkPoint &point) { fPoint = point; }
     168                 : 
     169                 :     // The next and previous vertices around the polygon.
     170               0 :     Vertex *next()                      { return fNext; }
     171               0 :     Vertex *prev()                      { return fPrev; }
     172               0 :     const Vertex *next() const          { return fNext; }
     173               0 :     const Vertex *prev() const          { return fPrev; }
     174               0 :     void setNext(Vertex *next)          { fNext = next; }
     175               0 :     void setPrev(Vertex *prev)          { fPrev = prev; }
     176                 : 
     177               0 :     void setDone(bool done)             { fDone = done; }
     178               0 :     bool done() const                   { return fDone; }
     179                 : 
     180                 :     // Trapezoid accessors return non-null for any complete trapezoids.
     181               0 :     void trapezoids(Trapezoid **trap0, Trapezoid **trap1) {
     182               0 :         *trap0 = (fTrap0.bottom() != NULL) ? &fTrap0 : NULL;
     183               0 :         *trap1 = (fTrap1.bottom() != NULL) ? &fTrap1 : NULL;
     184               0 :     }
     185                 : 
     186                 :     // Eliminate a trapezoid.
     187               0 :     void nullifyTrapezoid() {
     188               0 :         if (fTrap1.bottom() != NULL) {
     189               0 :             DebugPrintf("Unexpected non-null second trapezoid.\n");
     190               0 :             fTrap1.nullify();
     191               0 :             return;
     192                 :         }
     193               0 :         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               0 :     void delink() {
     206               0 :         Vertex *p = prev(),
     207               0 :                *n = next();
     208               0 :         p->setNext(n);
     209               0 :         n->setPrev(p);
     210               0 :     }
     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                 : 
     223                 : private:
     224                 :     SkPoint fPoint;
     225                 :     Vertex *fNext;
     226                 :     Vertex *fPrev;
     227                 :     bool fDone;
     228                 : };
     229                 : 
     230                 : 
     231               0 : bool Vertex::angleIsConvex() {
     232               0 :     SkPoint vPrev = prev()->point() - point(),
     233               0 :             vNext = next()->point() - point();
     234                 :     // TODO(turk): There might be overflow in fixed-point.
     235               0 :     return SkPoint::CrossProduct(vNext, vPrev) >= 0;
     236                 : }
     237                 : 
     238                 : 
     239               0 : bool Vertex::shareEdge(Vertex *top, Vertex *bottom) {
     240               0 :     return (((this == top)    && (this->next() == bottom)) ||
     241               0 :             ((this == bottom) && (this->next() == top)));
     242                 : }
     243                 : 
     244                 : 
     245               0 : SkScalar Vertex::compare(const SkPoint &pt) const  {
     246               0 :     SkPoint ve = next()->point() - point(),
     247               0 :             vp = pt              - point();
     248                 :     SkScalar d;
     249               0 :     if (ve.fY == 0) {
     250                 :         // Return twice the distance to the center of the horizontal edge.
     251               0 :         d = ve.fX + pt.fX - next()->point().fX;
     252                 :     } else {
     253                 :         // Return the distance to the edge, scaled by the edge length.
     254               0 :         d = SkPoint::CrossProduct(ve, vp);
     255               0 :         if (ve.fY > 0) d = -d;
     256                 :     }
     257               0 :     return d;
     258                 : }
     259                 : 
     260                 : 
     261               0 : SkScalar Trapezoid::compare(const SkPoint &pt) const {
     262               0 :     SkScalar d = left()->compare(pt);
     263               0 :     if (d <= 0)
     264               0 :         return d;   // Left of the left edge.
     265               0 :     d = right()->compare(pt);
     266               0 :     if (d >= 0)
     267               0 :         return d;   // Right of the right edge.
     268               0 :     return 0;       // Somewhere between the left and the right edges.
     269                 : }
     270                 : 
     271                 : 
     272                 : 
     273               0 : SkScalar Trapezoid::compare(const Trapezoid &t1) const {
     274                 : #if 1
     275               0 :     SkScalar d = left()->compare(t1.left()->point());
     276               0 :     if (d == 0)
     277               0 :         d = right()->compare(t1.right()->point());
     278               0 :     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                 : 
     291               0 : Trapezoid* ActiveTrapezoids::getTrapezoidWithEdge(const Vertex *edge) {
     292                 :     DebugPrintf("Entering getTrapezoidWithEdge(): looking through %d\n",
     293               0 :            fTrapezoids.count());
     294               0 :     DebugPrintf("trying to find %p: ", edge);
     295                 :     Trapezoid **tp;
     296               0 :     for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
     297               0 :         SkASSERT(tp != NULL);
     298               0 :         SkASSERT(*tp != NULL);
     299               0 :         DebugPrintf("%p and %p, ", (**tp).left(), (**tp).right());
     300               0 :         if ((**tp).left() == edge || (**tp).right() == edge) {
     301               0 :             DebugPrintf("\ngetTrapezoidWithEdge found the trapezoid\n");
     302               0 :             return *tp;
     303                 :         }
     304                 :     }
     305               0 :     DebugPrintf("getTrapezoidWithEdge found no trapezoid\n");
     306               0 :     return NULL;
     307                 : }
     308                 : 
     309                 : 
     310               0 : bool ActiveTrapezoids::insertNewTrapezoid(Vertex *vt,
     311                 :                                           Vertex *left,
     312                 :                                           Vertex *right) {
     313               0 :     DebugPrintf("Inserting a trapezoid...");
     314               0 :     if (vt->fTrap0.left() == NULL && vt->fTrap0.right() == NULL) {
     315               0 :         vt->fTrap0.setLeft(left);
     316               0 :         vt->fTrap0.setRight(right);
     317               0 :         insert(&vt->fTrap0);
     318               0 :     } else if (vt->fTrap1.left() == NULL && vt->fTrap1.right() == NULL) {
     319               0 :         DebugPrintf("a second one...");
     320               0 :         vt->fTrap1.setLeft(left);
     321               0 :         vt->fTrap1.setRight(right);
     322               0 :         if (vt->fTrap1 < vt->fTrap0) {  // Keep trapezoids sorted.
     323               0 :             remove(&vt->fTrap0);
     324               0 :             Trapezoid t = vt->fTrap0;
     325               0 :             vt->fTrap0 = vt->fTrap1;
     326               0 :             vt->fTrap1 = t;
     327               0 :             insert(&vt->fTrap0);
     328                 :         }
     329               0 :         insert(&vt->fTrap1);
     330                 :     } else {
     331               0 :         FailureMessage("More than 2 trapezoids requested for a vertex\n");
     332               0 :         return false;
     333                 :     }
     334               0 :     DebugPrintf(" done. %d incomplete trapezoids\n", fTrapezoids.count());
     335               0 :     return true;
     336                 : }
     337                 : 
     338                 : 
     339               0 : void ActiveTrapezoids::insert(Trapezoid *t) {
     340                 :     Trapezoid **tp;
     341               0 :     for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp)
     342               0 :         if (**tp > *t)
     343               0 :             break;
     344               0 :     fTrapezoids.insert(tp - fTrapezoids.begin(), 1, &t);
     345                 :     // SHOULD VERIFY THAT ALL TRAPEZOIDS ARE PROPERLY SORTED
     346               0 : }
     347                 : 
     348                 : 
     349               0 : void ActiveTrapezoids::remove(Trapezoid *t) {
     350               0 :     DebugPrintf("Removing a trapezoid...");
     351               0 :     for (Trapezoid **tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) {
     352               0 :         if (*tp == t) {
     353               0 :             fTrapezoids.remove(tp - fTrapezoids.begin());
     354               0 :             DebugPrintf(" done.\n");
     355               0 :             return;
     356                 :         }
     357                 :     }
     358               0 :     DebugPrintf(" Arghh! Panic!\n");
     359               0 :     SkASSERT(t == 0);   // Cannot find t in active trapezoid list.
     360                 : }
     361                 : 
     362                 : 
     363               0 : bool ActiveTrapezoids::withinActiveTrapezoid(const SkPoint &pt,
     364                 :                                              Trapezoid **trap) {
     365               0 :     DebugPrintf("Entering withinActiveTrapezoid()\n");
     366                 :     // This is where a good search data structure would be helpful.
     367                 :     Trapezoid **t;
     368               0 :     for (t = fTrapezoids.begin(); t < fTrapezoids.end(); ++t) {
     369               0 :         if ((**t).left()->compare(pt) <= 0) {
     370                 :             // The point is to the left of the left edge of this trapezoid.
     371               0 :             DebugPrintf("withinActiveTrapezoid: Before a trapezoid\n");
     372               0 :             *trap = *t;     // Return the place where a new trapezoid would go.
     373                 : // We have a bug with the sorting -- look through everything.
     374               0 :             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               0 :         if ((**t).right()->compare(pt) < 0) {
     380                 :             // The point is to the left of the right edge.
     381               0 :             DebugPrintf("withinActiveTrapezoid: Within an Active Trapezoid\n");
     382               0 :             *trap = *t;
     383               0 :             return true;
     384                 :         }
     385                 :     }
     386                 : 
     387                 :     // The point is to the right of all trapezoids.
     388               0 :     DebugPrintf("withinActiveTrapezoid: After all trapezoids\n");
     389               0 :     *trap = NULL;
     390               0 :     return false;
     391                 : }
     392                 : 
     393                 : 
     394               0 : Vertex* Vertex::diagonal() {
     395               0 :     Vertex *diag = NULL;
     396               0 :     if (fTrap0.bottom() != NULL) {
     397               0 :         if (!fTrap0.left() ->shareEdge(this, fTrap0.bottom()) &&
     398               0 :             !fTrap0.right()->shareEdge(this, fTrap0.bottom())
     399                 :         ) {
     400               0 :             diag = fTrap0.bottom();
     401               0 :             fTrap0 = fTrap1;
     402               0 :             fTrap1.nullify();
     403               0 :         } else if (fTrap1.bottom() != NULL &&
     404               0 :                   !fTrap1.left() ->shareEdge(this, fTrap1.bottom()) &&
     405               0 :                   !fTrap1.right()->shareEdge(this, fTrap1.bottom())
     406                 :         ) {
     407               0 :             diag = fTrap1.bottom();
     408               0 :             fTrap1.nullify();
     409                 :         }
     410                 :     }
     411               0 :     return diag;
     412                 : }
     413                 : 
     414                 : 
     415                 : // We use this to sort the edges vertically for a scan-conversion type of
     416                 : // operation.
     417                 : class VertexPtr {
     418                 : public:
     419                 :     Vertex *vt;
     420                 : };
     421                 : 
     422                 : 
     423               0 : bool operator<(VertexPtr &v0, VertexPtr &v1) {
     424                 :     // DebugPrintf("< %p %p\n", &v0, &v1);
     425               0 :     if (v0.vt->point().fY < v1.vt->point().fY)  return true;
     426               0 :     if (v0.vt->point().fY > v1.vt->point().fY)  return false;
     427               0 :     if (v0.vt->point().fX < v1.vt->point().fX)  return true;
     428               0 :     else                                        return false;
     429                 : }
     430                 : 
     431                 : 
     432               0 : bool operator>(VertexPtr &v0, VertexPtr &v1) {
     433                 :     // DebugPrintf("> %p %p\n", &v0, &v1);
     434               0 :     if (v0.vt->point().fY > v1.vt->point().fY)  return true;
     435               0 :     if (v0.vt->point().fY < v1.vt->point().fY)  return false;
     436               0 :     if (v0.vt->point().fX > v1.vt->point().fX)  return true;
     437               0 :     else                                        return false;
     438                 : }
     439                 : 
     440                 : 
     441               0 : static void SetVertexPoints(size_t numPts, const SkPoint *pt, Vertex *vt) {
     442               0 :     for (; numPts-- != 0; ++pt, ++vt)
     443               0 :         vt->setPoint(*pt);
     444               0 : }
     445                 : 
     446                 : 
     447               0 : static void InitializeVertexTopology(size_t numPts, Vertex *v1) {
     448               0 :     Vertex *v0 = v1 + numPts - 1, *v_1 = v0 - 1;
     449               0 :     for (; numPts-- != 0; v_1 = v0, v0 = v1++) {
     450               0 :         v0->setPrev(v_1);
     451               0 :         v0->setNext(v1);
     452                 :     }
     453               0 : }
     454                 : 
     455               0 : Vertex::VertexType Vertex::classify(Vertex **e0, Vertex **e1) {
     456                 :     VertexType type;
     457                 :     SkPoint vPrev, vNext;
     458               0 :     vPrev.fX = prev()->point().fX - point().fX;
     459               0 :     vPrev.fY = prev()->point().fY - point().fY;
     460               0 :     vNext.fX = next()->point().fX - point().fX;
     461               0 :     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               0 :     if (vPrev.fY < 0) {
     466               0 :         if (vNext.fY > 0) {
     467                 :             // Prev comes from above, Next goes below.
     468               0 :             type = MONOTONE;
     469               0 :             *e0 = prev();
     470               0 :             *e1 = this;
     471               0 :         } else if (vNext.fY < 0) {
     472                 :             // The are both above: sort so that e0 is on the left.
     473               0 :             type = CONCAVE;
     474               0 :             if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
     475               0 :                 *e0 = this;
     476               0 :                 *e1 = prev();
     477                 :             } else {
     478               0 :                 *e0 = prev();
     479               0 :                 *e1 = this;
     480                 :             }
     481                 :         } else {
     482               0 :             DebugPrintf("### py < 0, ny = 0\n");
     483               0 :             if (vNext.fX < 0) {
     484               0 :                 type = CONCAVE;
     485               0 :                 *e0 = this;     // flat to the left
     486               0 :                 *e1 = prev();   // concave on the right
     487                 :             } else {
     488               0 :                 type = CONCAVE;
     489               0 :                 *e0 = prev();   // concave to the left
     490               0 :                 *e1 = this;     // flat to the right
     491                 :             }
     492                 :         }
     493               0 :     } else if (vPrev.fY > 0) {
     494               0 :         if (vNext.fY < 0) {
     495                 :             // Next comes from above, Prev goes below.
     496               0 :             type = MONOTONE;
     497               0 :             *e0 = this;
     498               0 :             *e1 = prev();
     499               0 :         } else if (vNext.fY > 0) {
     500                 :             // They are both below: sort so that e0 is on the left.
     501               0 :             type = CONVEX;
     502               0 :             if (SkPoint::CrossProduct(vPrev, vNext) <= 0) {
     503               0 :                 *e0 = prev();
     504               0 :                 *e1 = this;
     505                 :             } else {
     506               0 :                 *e0 = this;
     507               0 :                 *e1 = prev();
     508                 :             }
     509                 :         } else {
     510               0 :             DebugPrintf("### py > 0, ny = 0\n");
     511               0 :             if (vNext.fX < 0) {
     512               0 :                 type = MONOTONE;
     513               0 :                 *e0 = this;     // flat to the left
     514               0 :                 *e1 = prev();   // convex on the right - try monotone first
     515                 :             } else {
     516               0 :                 type = MONOTONE;
     517               0 :                 *e0 = prev();   // convex to the left - try monotone first
     518               0 :                 *e1 = this;     // flat to the right
     519                 :             }
     520                 :         }
     521                 :     } else {  // vPrev.fY == 0
     522               0 :         if (vNext.fY < 0) {
     523               0 :             DebugPrintf("### py = 0, ny < 0\n");
     524               0 :             if (vPrev.fX < 0) {
     525               0 :                 type = CONCAVE;
     526               0 :                 *e0 = prev();   // flat to the left
     527               0 :                 *e1 = this;     // concave on the right
     528                 :             } else {
     529               0 :                 type = CONCAVE;
     530               0 :                 *e0 = this;     // concave on the left - defer
     531               0 :                 *e1 = prev();   // flat to the right
     532                 :             }
     533               0 :         } else if (vNext.fY > 0) {
     534               0 :             DebugPrintf("### py = 0, ny > 0\n");
     535               0 :             if (vPrev.fX < 0) {
     536               0 :                 type = MONOTONE;
     537               0 :                 *e0 = prev();   // flat to the left
     538               0 :                 *e1 = this;     // convex on the right - try monotone first
     539                 :             } else {
     540               0 :                 type = MONOTONE;
     541               0 :                 *e0 = this;     // convex to the left - try monotone first
     542               0 :                 *e1 = prev();   // flat to the right
     543                 :             }
     544                 :         } else {
     545               0 :             DebugPrintf("### py = 0, ny = 0\n");
     546                 :             // First we try concave, then monotone, then convex.
     547               0 :             if (vPrev.fX <= vNext.fX) {
     548               0 :                 type = CONCAVE;
     549               0 :                 *e0 = prev();   // flat to the left
     550               0 :                 *e1 = this;     // flat to the right
     551                 :             } else {
     552               0 :                 type = CONCAVE;
     553               0 :                 *e0 = this;     // flat to the left
     554               0 :                 *e1 = prev();   // flat to the right
     555                 :             }
     556                 :         }
     557                 :     }
     558               0 :     return type;
     559                 : }
     560                 : 
     561                 : 
     562                 : #ifdef DEBUG
     563               0 : static const char* GetVertexTypeString(Vertex::VertexType type) {
     564               0 :     const char *typeStr = NULL;
     565               0 :     switch (type) {
     566                 :         case Vertex::MONOTONE:
     567               0 :             typeStr = "MONOTONE";
     568               0 :             break;
     569                 :         case Vertex::CONCAVE:
     570               0 :             typeStr = "CONCAVE";
     571               0 :             break;
     572                 :         case Vertex::CONVEX:
     573               0 :             typeStr = "CONVEX";
     574               0 :             break;
     575                 :     }
     576               0 :     return typeStr;
     577                 : }
     578                 : 
     579                 : 
     580               0 : static void PrintVertices(size_t numPts, Vertex *vt) {
     581               0 :     DebugPrintf("\nVertices:\n");
     582               0 :     for (size_t i = 0; i < numPts; i++) {
     583                 :         Vertex *e0, *e1;
     584               0 :         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               0 :                     i, vt[i].point().fX, vt[i].point().fY,
     588               0 :                     vt[i].prev() - vt, vt[i].next() - vt,
     589               0 :                     GetVertexTypeString(type), e0 - vt, e1 - vt);
     590                 :         Trapezoid *trap[2];
     591               0 :         vt[i].trapezoids(trap, trap+1);
     592               0 :         for (int j = 0; j < 2; ++j) {
     593               0 :             if (trap[j] != NULL) {
     594                 :                 DebugPrintf(", trap(L=%d, R=%d, B=%d)",
     595               0 :                             trap[j]->left()   - vt,
     596               0 :                             trap[j]->right()  - vt,
     597               0 :                             trap[j]->bottom() - vt);
     598                 :             }
     599                 :         }
     600               0 :         DebugPrintf("\n");
     601                 :     }
     602               0 : }
     603                 : 
     604                 : 
     605               0 : static void PrintVertexPtrs(size_t numPts, VertexPtr *vp, Vertex *vtBase) {
     606               0 :     DebugPrintf("\nSorted Vertices:\n");
     607               0 :     for (size_t i = 0; i < numPts; i++) {
     608                 :         Vertex *e0, *e1;
     609               0 :         Vertex *vt = vp[i].vt;
     610               0 :         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               0 :                     i, vt - vtBase, vt->point().fX, vt->point().fY,
     614               0 :                     vt->prev() - vtBase, vt->next() - vtBase,
     615               0 :                     GetVertexTypeString(type), e0 - vtBase, e1 - vtBase);
     616                 :         Trapezoid *trap[2];
     617               0 :         vt->trapezoids(trap, trap+1);
     618               0 :         for (int j = 0; j < 2; ++j) {
     619               0 :             if (trap[j] != NULL) {
     620                 :                 DebugPrintf(", trap(L=%d, R=%d, B=%d)",
     621               0 :                             trap[j]->left()   - vtBase,
     622               0 :                             trap[j]->right()  - vtBase,
     623               0 :                             trap[j]->bottom() - vtBase);
     624                 :             }
     625                 :         }
     626               0 :         DebugPrintf("\n");
     627                 :     }
     628               0 : }
     629                 : #else  // !DEBUG
     630                 : inline void PrintVertices(size_t numPts, Vertex *vt) {}
     631                 : inline 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.
     636                 : template <typename T>
     637               0 : void BubbleSort(T *array, size_t count) {
     638                 :     bool sorted;
     639               0 :     size_t count_1 = count - 1;
     640               0 :     do {
     641               0 :         sorted = true;
     642               0 :         for (size_t i = 0; i < count_1; ++i) {
     643               0 :             if (array[i + 1] < array[i]) {
     644               0 :                 T t = array[i];
     645               0 :                 array[i] = array[i + 1];
     646               0 :                 array[i + 1] = t;
     647               0 :                 sorted = false;
     648                 :             }
     649                 :         }
     650                 :     } while (!sorted);
     651               0 : }
     652                 : 
     653                 : 
     654                 : // Remove zero-height trapezoids.
     655               0 : static void RemoveDegenerateTrapezoids(size_t numVt, Vertex *vt) {
     656               0 :     for (; numVt-- != 0; vt++) {
     657                 :         Trapezoid *traps[2];
     658               0 :         vt->trapezoids(traps, traps+1);
     659               0 :         if (traps[1] != NULL &&
     660               0 :                 vt->point().fY >= traps[1]->bottom()->point().fY) {
     661               0 :             traps[1]->nullify();
     662               0 :             traps[1] = NULL;
     663                 :         }
     664               0 :         if (traps[0] != NULL &&
     665               0 :                 vt->point().fY >= traps[0]->bottom()->point().fY) {
     666               0 :             if (traps[1] != NULL) {
     667               0 :                 *traps[0] = *traps[1];
     668               0 :                 traps[1]->nullify();
     669                 :             } else {
     670               0 :                 traps[0]->nullify();
     671                 :             }
     672                 :         }
     673                 :     }
     674               0 : }
     675                 : 
     676                 : 
     677                 : // Enhance the polygon with trapezoids.
     678               0 : bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) {
     679               0 :     DebugPrintf("ConvertPointsToVertices()\n");
     680                 : 
     681                 :     // Clear everything.
     682               0 :     DebugPrintf("Zeroing vertices\n");
     683               0 :     sk_bzero(vta, numPts * sizeof(*vta));
     684                 : 
     685                 :     // Initialize vertices.
     686               0 :     DebugPrintf("Initializing vertices\n");
     687               0 :     SetVertexPoints(numPts, pts, vta);
     688               0 :     InitializeVertexTopology(numPts, vta);
     689                 : 
     690               0 :     PrintVertices(numPts, vta);
     691                 : 
     692               0 :     SkTDArray<VertexPtr> vtptr;
     693               0 :     vtptr.setCount(numPts);
     694               0 :     for (int i = numPts; i-- != 0;)
     695               0 :         vtptr[i].vt = vta + i;
     696               0 :     PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
     697                 :     DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(),
     698               0 :         &vtptr[0], &vtptr[vtptr.count() - 1]
     699               0 :     );
     700                 : //  SkTHeapSort(vtptr.begin(), vtptr.count());
     701               0 :     BubbleSort(vtptr.begin(), vtptr.count());
     702               0 :     DebugPrintf("Done sorting\n");
     703               0 :     PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
     704                 : 
     705               0 :     DebugPrintf("Traversing sorted vertrap ptrs\n");
     706               0 :     ActiveTrapezoids incompleteTrapezoids;
     707               0 :     for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) {
     708                 :         DebugPrintf("%d: sorted vertrap %d\n",
     709               0 :                     vtpp - vtptr.begin(), vtpp->vt - vta);
     710               0 :         Vertex *vt = vtpp->vt;
     711                 :         Vertex *e0, *e1;
     712                 :         Trapezoid *t;
     713               0 :         switch (vt->classify(&e0, &e1)) {
     714                 :             case Vertex::MONOTONE:
     715                 :             monotone:
     716               0 :                 DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta);
     717                 :                 // We should find one edge.
     718               0 :                 t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
     719               0 :                 if (t == NULL) {      // One of the edges is flat.
     720                 :                     DebugPrintf("Monotone: cannot find a trapezoid with e0: "
     721               0 :                                 "trying convex\n");
     722               0 :                     goto convex;
     723                 :                 }
     724               0 :                 t->setBottom(vt);     // This trapezoid is now complete.
     725               0 :                 incompleteTrapezoids.remove(t);
     726                 : 
     727               0 :                 if (e0 == t->left())  // Replace the left edge.
     728               0 :                     incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
     729                 :                 else                  // Replace the right edge.
     730               0 :                     incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1);
     731               0 :                 break;
     732                 : 
     733                 :             case Vertex::CONVEX:      // Start of a new trapezoid.
     734                 :             convex:
     735                 :                 // We don't expect to find any edges.
     736               0 :                 DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta);
     737               0 :                 if (incompleteTrapezoids.withinActiveTrapezoid(
     738               0 :                         vt->point(), &t)) {
     739                 :                     // Complete trapezoid.
     740               0 :                     SkASSERT(t != NULL);
     741               0 :                     t->setBottom(vt);
     742               0 :                     incompleteTrapezoids.remove(t);
     743                 :                     // Introduce two new trapezoids.
     744               0 :                     incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0);
     745               0 :                     incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right());
     746                 :                 } else {
     747                 :                     // Insert a new trapezoid.
     748               0 :                     incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1);
     749                 :                 }
     750               0 :                 break;
     751                 : 
     752                 :             case Vertex::CONCAVE:   // End of a trapezoid.
     753               0 :                 DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta);
     754                 :                 // We should find two edges.
     755               0 :                 t = incompleteTrapezoids.getTrapezoidWithEdge(e0);
     756               0 :                 if (t == NULL) {
     757                 :                     DebugPrintf("Concave: cannot find a trapezoid with e0: "
     758               0 :                                 " trying monotone\n");
     759               0 :                     goto monotone;
     760                 :                 }
     761               0 :                 SkASSERT(t != NULL);
     762               0 :                 if (e0 == t->left() && e1 == t->right()) {
     763                 :                     DebugPrintf(
     764               0 :                             "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               0 :                     t->setBottom(vt);
     768               0 :                     incompleteTrapezoids.remove(t);
     769                 :                 } else {  // Edges belong to different trapezoids
     770                 :                     DebugPrintf(
     771               0 :                             "Concave edges belong to different trapezoids.\n");
     772                 :                     // Complete left and right trapezoids.
     773                 :                     Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge(
     774               0 :                                                                             e1);
     775               0 :                     if (s == NULL) {
     776                 :                         DebugPrintf(
     777                 :                                 "Concave: cannot find a trapezoid with e1: "
     778               0 :                                 " trying monotone\n");
     779               0 :                         goto monotone;
     780                 :                     }
     781               0 :                     t->setBottom(vt);
     782               0 :                     s->setBottom(vt);
     783               0 :                     incompleteTrapezoids.remove(t);
     784               0 :                     incompleteTrapezoids.remove(s);
     785                 : 
     786                 :                     // Merge the two trapezoids into one below this vertex.
     787                 :                     incompleteTrapezoids.insertNewTrapezoid(vt, t->left(),
     788               0 :                                                                 s->right());
     789                 :                 }
     790               0 :                 break;
     791                 :         }
     792                 :     }
     793                 : 
     794               0 :     RemoveDegenerateTrapezoids(numPts, vta);
     795                 : 
     796               0 :     DebugPrintf("Done making trapezoids\n");
     797               0 :     PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta);
     798                 : 
     799               0 :     size_t k = incompleteTrapezoids.count();
     800               0 :     if (k > 0) {
     801               0 :         FailureMessage("%d incomplete trapezoids\n", k);
     802               0 :         return false;
     803                 :     }
     804               0 :     return true;
     805                 : }
     806                 : 
     807                 : 
     808               0 : inline void appendTriangleAtVertex(const Vertex *v,
     809                 :                                    SkTDArray<SkPoint> *triangles) {
     810               0 :     SkPoint *p = triangles->append(3);
     811               0 :     p[0] = v->prev()->point();
     812               0 :     p[1] = v->point();
     813               0 :     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               0 :           p[1].fX, p[1].fY,
     818               0 :           p[2].fX, p[2].fY
     819               0 :     );
     820               0 : }
     821                 : 
     822                 : 
     823               0 : static size_t CountVertices(const Vertex *first, const Vertex *last) {
     824               0 :     DebugPrintf("Counting vertices: ");
     825               0 :     size_t count = 1;
     826               0 :     for (; first != last; first = first->next()) {
     827               0 :         ++count;
     828               0 :         SkASSERT(count <= kMaxCount);
     829               0 :         if (count >= kMaxCount) {
     830               0 :             FailureMessage("Vertices do not seem to be in a linked chain\n");
     831               0 :             break;
     832                 :         }
     833                 :     }
     834               0 :     return count;
     835                 : }
     836                 : 
     837                 : 
     838               0 : bool operator<(const SkPoint &p0, const SkPoint &p1) {
     839               0 :     if (p0.fY < p1.fY)  return true;
     840               0 :     if (p0.fY > p1.fY)  return false;
     841               0 :     if (p0.fX < p1.fX)  return true;
     842               0 :     else                return false;
     843                 : }
     844                 : 
     845                 : 
     846               0 : static void PrintLinkedVertices(size_t n, Vertex *vertices) {
     847               0 :     DebugPrintf("%d vertices:\n", n);
     848                 :     Vertex *v;
     849               0 :     for (v = vertices; n-- != 0; v = v->next())
     850               0 :         DebugPrintf("   (%.7g, %.7g)\n", v->point().fX, v->point().fY);
     851               0 :     if (v != vertices)
     852               0 :         FailureMessage("Vertices are not in a linked chain\n");
     853               0 : }
     854                 : 
     855                 : 
     856                 : // Triangulate an unimonotone chain.
     857               0 : bool TriangulateMonotone(Vertex *first, Vertex *last,
     858                 :                          SkTDArray<SkPoint> *triangles) {
     859               0 :     DebugPrintf("TriangulateMonotone()\n");
     860                 : 
     861               0 :     size_t numVertices = CountVertices(first, last);
     862               0 :     if (numVertices == kMaxCount) {
     863               0 :         FailureMessage("Way too many vertices: %d:\n", numVertices);
     864               0 :         PrintLinkedVertices(numVertices, first);
     865               0 :         return false;
     866                 :     }
     867                 : 
     868               0 :     Vertex *start = first;
     869                 :     // First find the point with the smallest Y.
     870               0 :     DebugPrintf("TriangulateMonotone: finding bottom\n");
     871               0 :     int count = kMaxCount;    // Maximum number of vertices.
     872               0 :     for (Vertex *v = first->next(); v != first && count-- > 0; v = v->next())
     873               0 :         if (v->point() < start->point())
     874               0 :             start = v;
     875               0 :     if (count <= 0) {
     876               0 :         FailureMessage("TriangulateMonotone() was given disjoint chain\n");
     877               0 :         return false;   // Something went wrong.
     878                 :     }
     879                 : 
     880                 :     // Start at the far end of the long edge.
     881               0 :     if (start->prev()->point() < start->next()->point())
     882               0 :         start = start->next();
     883                 : 
     884               0 :     Vertex *current = start->next();
     885               0 :     while (numVertices >= 3) {
     886               0 :         if (current->angleIsConvex()) {
     887               0 :             DebugPrintf("Angle %p is convex\n", current);
     888                 :             // Print the vertices
     889               0 :             PrintLinkedVertices(numVertices, start);
     890                 : 
     891               0 :             appendTriangleAtVertex(current, triangles);
     892               0 :             if (triangles->count() > kMaxCount * 3) {
     893                 :                 FailureMessage("An extraordinarily large number of triangles "
     894               0 :                                "were generated\n");
     895               0 :                 return false;
     896                 :             }
     897               0 :             Vertex *save = current->prev();
     898               0 :             current->delink();
     899               0 :             current = (save == start || save == start->prev()) ? start->next()
     900               0 :                                                                : save;
     901               0 :             --numVertices;
     902                 :         } else {
     903               0 :             if (numVertices == 3) {
     904               0 :                 FailureMessage("Convexity error in TriangulateMonotone()\n");
     905               0 :                 appendTriangleAtVertex(current, triangles);
     906               0 :                 return false;
     907                 :             }
     908               0 :             DebugPrintf("Angle %p is concave\n", current);
     909               0 :             current = current->next();
     910                 :         }
     911                 :     }
     912               0 :     return true;
     913                 : }
     914                 : 
     915                 : 
     916                 : // Split the polygon into sets of unimonotone chains, and eventually call
     917                 : // TriangulateMonotone() to convert them into triangles.
     918               0 : bool Triangulate(Vertex *first, Vertex *last, SkTDArray<SkPoint> *triangles) {
     919               0 :     DebugPrintf("Triangulate()\n");
     920               0 :     Vertex *currentVertex = first;
     921               0 :     while (!currentVertex->done()) {
     922               0 :         currentVertex->setDone(true);
     923               0 :         Vertex *bottomVertex = currentVertex->diagonal();
     924               0 :         if (bottomVertex != NULL) {
     925               0 :             Vertex *saveNext = currentVertex->next();
     926               0 :             Vertex *savePrev = bottomVertex->prev();
     927               0 :             currentVertex->setNext(bottomVertex);
     928               0 :             bottomVertex->setPrev(currentVertex);
     929               0 :             currentVertex->nullifyTrapezoid();
     930               0 :             bool success = Triangulate(bottomVertex, currentVertex, triangles);
     931               0 :             currentVertex->setDone(false);
     932               0 :             bottomVertex->setDone(false);
     933               0 :             currentVertex->setNext(saveNext);
     934               0 :             bottomVertex->setPrev(savePrev);
     935               0 :             bottomVertex->setNext(currentVertex);
     936               0 :             currentVertex->setPrev(bottomVertex);
     937               0 :             return Triangulate(currentVertex, bottomVertex, triangles)
     938               0 :                    && success;
     939                 :         } else {
     940               0 :             currentVertex = currentVertex->next();
     941                 :         }
     942                 :     }
     943               0 :     return TriangulateMonotone(first, last, triangles);
     944                 : }
     945                 : 
     946                 : 
     947               0 : bool SkConcaveToTriangles(size_t numPts,
     948                 :                           const SkPoint pts[],
     949                 :                           SkTDArray<SkPoint> *triangles) {
     950               0 :     DebugPrintf("SkConcaveToTriangles()\n");
     951                 : 
     952               0 :     SkTDArray<Vertex> vertices;
     953               0 :     vertices.setCount(numPts);
     954               0 :     if (!ConvertPointsToVertices(numPts, pts, vertices.begin()))
     955               0 :         return false;
     956                 : 
     957               0 :     triangles->setReserve(numPts);
     958               0 :     triangles->setCount(0);
     959               0 :     return Triangulate(vertices.begin(), vertices.end() - 1, triangles);
     960                 : }

Generated by: LCOV version 1.7