Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 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 #include "SkBuffer.h"
     11 #include "SkErrorInternals.h"
     12 #include "SkMath.h"
     13 #include "SkPath.h"
     14 #include "SkPathRef.h"
     15 #include "SkRRect.h"
     16 #include "SkThread.h"
     17 
     18 SK_DEFINE_INST_COUNT(SkPath);
     19 
     20 // This value is just made-up for now. When count is 4, calling memset was much
     21 // slower than just writing the loop. This seems odd, and hopefully in the
     22 // future this we appear to have been a fluke...
     23 #define MIN_COUNT_FOR_MEMSET_TO_BE_FAST 16
     24 
     25 ////////////////////////////////////////////////////////////////////////////
     26 
     27 /**
     28  *  Path.bounds is defined to be the bounds of all the control points.
     29  *  If we called bounds.join(r) we would skip r if r was empty, which breaks
     30  *  our promise. Hence we have a custom joiner that doesn't look at emptiness
     31  */
     32 static void joinNoEmptyChecks(SkRect* dst, const SkRect& src) {
     33     dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft);
     34     dst->fTop = SkMinScalar(dst->fTop, src.fTop);
     35     dst->fRight = SkMaxScalar(dst->fRight, src.fRight);
     36     dst->fBottom = SkMaxScalar(dst->fBottom, src.fBottom);
     37 }
     38 
     39 static bool is_degenerate(const SkPath& path) {
     40     SkPath::Iter iter(path, false);
     41     SkPoint pts[4];
     42     return SkPath::kDone_Verb == iter.next(pts);
     43 }
     44 
     45 class SkAutoDisableOvalCheck {
     46 public:
     47     SkAutoDisableOvalCheck(SkPath* path) : fPath(path) {
     48         fSaved = fPath->fIsOval;
     49     }
     50 
     51     ~SkAutoDisableOvalCheck() {
     52         fPath->fIsOval = fSaved;
     53     }
     54 
     55 private:
     56     SkPath* fPath;
     57     bool    fSaved;
     58 };
     59 
     60 class SkAutoDisableDirectionCheck {
     61 public:
     62     SkAutoDisableDirectionCheck(SkPath* path) : fPath(path) {
     63         fSaved = static_cast<SkPath::Direction>(fPath->fDirection);
     64     }
     65 
     66     ~SkAutoDisableDirectionCheck() {
     67         fPath->fDirection = fSaved;
     68     }
     69 
     70 private:
     71     SkPath*              fPath;
     72     SkPath::Direction    fSaved;
     73 };
     74 
     75 /*  This guy's constructor/destructor bracket a path editing operation. It is
     76     used when we know the bounds of the amount we are going to add to the path
     77     (usually a new contour, but not required).
     78 
     79     It captures some state about the path up front (i.e. if it already has a
     80     cached bounds), and the if it can, it updates the cache bounds explicitly,
     81     avoiding the need to revisit all of the points in getBounds().
     82 
     83     It also notes if the path was originally degenerate, and if so, sets
     84     isConvex to true. Thus it can only be used if the contour being added is
     85     convex.
     86  */
     87 class SkAutoPathBoundsUpdate {
     88 public:
     89     SkAutoPathBoundsUpdate(SkPath* path, const SkRect& r) : fRect(r) {
     90         this->init(path);
     91     }
     92 
     93     SkAutoPathBoundsUpdate(SkPath* path, SkScalar left, SkScalar top,
     94                            SkScalar right, SkScalar bottom) {
     95         fRect.set(left, top, right, bottom);
     96         this->init(path);
     97     }
     98 
     99     ~SkAutoPathBoundsUpdate() {
    100         fPath->setIsConvex(fDegenerate);
    101         if (fEmpty) {
    102             fPath->fBounds = fRect;
    103             fPath->fBoundsIsDirty = false;
    104             fPath->fIsFinite = fPath->fBounds.isFinite();
    105         } else if (!fDirty) {
    106             joinNoEmptyChecks(&fPath->fBounds, fRect);
    107             fPath->fBoundsIsDirty = false;
    108             fPath->fIsFinite = fPath->fBounds.isFinite();
    109         }
    110     }
    111 
    112 private:
    113     SkPath* fPath;
    114     SkRect  fRect;
    115     bool    fDirty;
    116     bool    fDegenerate;
    117     bool    fEmpty;
    118 
    119     // returns true if we should proceed
    120     void init(SkPath* path) {
    121         fPath = path;
    122         // Mark the path's bounds as dirty if (1) they are, or (2) the path
    123         // is non-finite, and therefore its bounds are not meaningful
    124         fDirty = SkToBool(path->fBoundsIsDirty) || !path->fIsFinite;
    125         fDegenerate = is_degenerate(*path);
    126         fEmpty = path->isEmpty();
    127         // Cannot use fRect for our bounds unless we know it is sorted
    128         fRect.sort();
    129     }
    130 };
    131 
    132 // Return true if the computed bounds are finite.
    133 static bool compute_pt_bounds(SkRect* bounds, const SkPathRef& ref) {
    134     int count = ref.countPoints();
    135     if (count <= 1) {  // we ignore just 1 point (moveto)
    136         bounds->setEmpty();
    137         return count ? ref.points()->isFinite() : true;
    138     } else {
    139         return bounds->setBoundsCheck(ref.points(), count);
    140     }
    141 }
    142 
    143 ////////////////////////////////////////////////////////////////////////////
    144 
    145 /*
    146     Stores the verbs and points as they are given to us, with exceptions:
    147     - we only record "Close" if it was immediately preceeded by Move | Line | Quad | Cubic
    148     - we insert a Move(0,0) if Line | Quad | Cubic is our first command
    149 
    150     The iterator does more cleanup, especially if forceClose == true
    151     1. If we encounter degenerate segments, remove them
    152     2. if we encounter Close, return a cons'd up Line() first (if the curr-pt != start-pt)
    153     3. if we encounter Move without a preceeding Close, and forceClose is true, goto #2
    154     4. if we encounter Line | Quad | Cubic after Close, cons up a Move
    155 */
    156 
    157 ////////////////////////////////////////////////////////////////////////////
    158 
    159 // flag to require a moveTo if we begin with something else, like lineTo etc.
    160 #define INITIAL_LASTMOVETOINDEX_VALUE   ~0
    161 
    162 SkPath::SkPath()
    163     : fPathRef(SkPathRef::CreateEmpty())
    164 #ifdef SK_BUILD_FOR_ANDROID
    165     , fGenerationID(0)
    166 #endif
    167 {
    168     this->resetFields();
    169 }
    170 
    171 void SkPath::resetFields() {
    172     //fPathRef is assumed to have been emptied by the caller.
    173     fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE;
    174     fFillType = kWinding_FillType;
    175     fSegmentMask = 0;
    176     fBoundsIsDirty = true;
    177     fConvexity = kUnknown_Convexity;
    178     fDirection = kUnknown_Direction;
    179     fIsFinite = false;
    180     fIsOval = false;
    181 #ifdef SK_BUILD_FOR_ANDROID
    182     GEN_ID_INC;
    183     fSourcePath = NULL;
    184 #endif
    185 }
    186 
    187 SkPath::SkPath(const SkPath& that)
    188     : fPathRef(SkRef(that.fPathRef.get())) {
    189     this->copyFields(that);
    190 #ifdef SK_BUILD_FOR_ANDROID
    191     fGenerationID = that.fGenerationID;
    192     fSourcePath   = NULL;  // TODO(mtklein): follow up with Android: do we want to copy this too?
    193 #endif
    194     SkDEBUGCODE(that.validate();)
    195 }
    196 
    197 SkPath::~SkPath() {
    198     SkDEBUGCODE(this->validate();)
    199 }
    200 
    201 SkPath& SkPath::operator=(const SkPath& that) {
    202     SkDEBUGCODE(that.validate();)
    203 
    204     if (this != &that) {
    205         fPathRef.reset(SkRef(that.fPathRef.get()));
    206         this->copyFields(that);
    207 #ifdef SK_BUILD_FOR_ANDROID
    208         GEN_ID_INC;  // Similar to swap, we can't just copy this or it could go back in time.
    209         fSourcePath = NULL;  // TODO(mtklein): follow up with Android: do we want to copy this too?
    210 #endif
    211     }
    212     SkDEBUGCODE(this->validate();)
    213     return *this;
    214 }
    215 
    216 void SkPath::copyFields(const SkPath& that) {
    217     //fPathRef is assumed to have been set by the caller.
    218     fBounds          = that.fBounds;
    219     fLastMoveToIndex = that.fLastMoveToIndex;
    220     fFillType        = that.fFillType;
    221     fSegmentMask     = that.fSegmentMask;
    222     fBoundsIsDirty   = that.fBoundsIsDirty;
    223     fConvexity       = that.fConvexity;
    224     fDirection       = that.fDirection;
    225     fIsFinite        = that.fIsFinite;
    226     fIsOval          = that.fIsOval;
    227 }
    228 
    229 bool operator==(const SkPath& a, const SkPath& b) {
    230     // note: don't need to look at isConvex or bounds, since just comparing the
    231     // raw data is sufficient.
    232 
    233     // We explicitly check fSegmentMask as a quick-reject. We could skip it,
    234     // since it is only a cache of info in the fVerbs, but its a fast way to
    235     // notice a difference
    236 
    237     return &a == &b ||
    238         (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask &&
    239          *a.fPathRef.get() == *b.fPathRef.get());
    240 }
    241 
    242 void SkPath::swap(SkPath& that) {
    243     SkASSERT(&that != NULL);
    244 
    245     if (this != &that) {
    246         fPathRef.swap(&that.fPathRef);
    247         SkTSwap<SkRect>(fBounds, that.fBounds);
    248         SkTSwap<int>(fLastMoveToIndex, that.fLastMoveToIndex);
    249         SkTSwap<uint8_t>(fFillType, that.fFillType);
    250         SkTSwap<uint8_t>(fSegmentMask, that.fSegmentMask);
    251         SkTSwap<uint8_t>(fBoundsIsDirty, that.fBoundsIsDirty);
    252         SkTSwap<uint8_t>(fConvexity, that.fConvexity);
    253         SkTSwap<uint8_t>(fDirection, that.fDirection);
    254         SkTSwap<SkBool8>(fIsFinite, that.fIsFinite);
    255         SkTSwap<SkBool8>(fIsOval, that.fIsOval);
    256 #ifdef SK_BUILD_FOR_ANDROID
    257         // It doesn't really make sense to swap the generation IDs here, because they might go
    258         // backwards.  To be safe we increment both to mark them both as changed.
    259         GEN_ID_INC;
    260         GEN_ID_PTR_INC(&that);
    261         SkTSwap<const SkPath*>(fSourcePath, that.fSourcePath);
    262 #endif
    263     }
    264 }
    265 
    266 static inline bool check_edge_against_rect(const SkPoint& p0,
    267                                            const SkPoint& p1,
    268                                            const SkRect& rect,
    269                                            SkPath::Direction dir) {
    270     const SkPoint* edgeBegin;
    271     SkVector v;
    272     if (SkPath::kCW_Direction == dir) {
    273         v = p1 - p0;
    274         edgeBegin = &p0;
    275     } else {
    276         v = p0 - p1;
    277         edgeBegin = &p1;
    278     }
    279     if (v.fX || v.fY) {
    280         // check the cross product of v with the vec from edgeBegin to each rect corner
    281         SkScalar yL = SkScalarMul(v.fY, rect.fLeft - edgeBegin->fX);
    282         SkScalar xT = SkScalarMul(v.fX, rect.fTop - edgeBegin->fY);
    283         SkScalar yR = SkScalarMul(v.fY, rect.fRight - edgeBegin->fX);
    284         SkScalar xB = SkScalarMul(v.fX, rect.fBottom - edgeBegin->fY);
    285         if ((xT < yL) || (xT < yR) || (xB < yL) || (xB < yR)) {
    286             return false;
    287         }
    288     }
    289     return true;
    290 }
    291 
    292 bool SkPath::conservativelyContainsRect(const SkRect& rect) const {
    293     // This only handles non-degenerate convex paths currently.
    294     if (kConvex_Convexity != this->getConvexity()) {
    295         return false;
    296     }
    297 
    298     Direction direction;
    299     if (!this->cheapComputeDirection(&direction)) {
    300         return false;
    301     }
    302 
    303     SkPoint firstPt;
    304     SkPoint prevPt;
    305     RawIter iter(*this);
    306     SkPath::Verb verb;
    307     SkPoint pts[4];
    308     SkDEBUGCODE(int moveCnt = 0;)
    309     SkDEBUGCODE(int segmentCount = 0;)
    310     SkDEBUGCODE(int closeCount = 0;)
    311 
    312     while ((verb = iter.next(pts)) != kDone_Verb) {
    313         int nextPt = -1;
    314         switch (verb) {
    315             case kMove_Verb:
    316                 SkASSERT(!segmentCount && !closeCount);
    317                 SkDEBUGCODE(++moveCnt);
    318                 firstPt = prevPt = pts[0];
    319                 break;
    320             case kLine_Verb:
    321                 nextPt = 1;
    322                 SkASSERT(moveCnt && !closeCount);
    323                 SkDEBUGCODE(++segmentCount);
    324                 break;
    325             case kQuad_Verb:
    326             case kConic_Verb:
    327                 SkASSERT(moveCnt && !closeCount);
    328                 SkDEBUGCODE(++segmentCount);
    329                 nextPt = 2;
    330                 break;
    331             case kCubic_Verb:
    332                 SkASSERT(moveCnt && !closeCount);
    333                 SkDEBUGCODE(++segmentCount);
    334                 nextPt = 3;
    335                 break;
    336             case kClose_Verb:
    337                 SkDEBUGCODE(++closeCount;)
    338                 break;
    339             default:
    340                 SkDEBUGFAIL("unknown verb");
    341         }
    342         if (-1 != nextPt) {
    343             if (!check_edge_against_rect(prevPt, pts[nextPt], rect, direction)) {
    344                 return false;
    345             }
    346             prevPt = pts[nextPt];
    347         }
    348     }
    349 
    350     return check_edge_against_rect(prevPt, firstPt, rect, direction);
    351 }
    352 
    353 #ifdef SK_BUILD_FOR_ANDROID
    354 uint32_t SkPath::getGenerationID() const {
    355     return fGenerationID;
    356 }
    357 
    358 const SkPath* SkPath::getSourcePath() const {
    359     return fSourcePath;
    360 }
    361 
    362 void SkPath::setSourcePath(const SkPath* path) {
    363     fSourcePath = path;
    364 }
    365 #endif
    366 
    367 void SkPath::reset() {
    368     SkDEBUGCODE(this->validate();)
    369 
    370     fPathRef.reset(SkPathRef::CreateEmpty());
    371     this->resetFields();
    372 }
    373 
    374 void SkPath::rewind() {
    375     SkDEBUGCODE(this->validate();)
    376 
    377     SkPathRef::Rewind(&fPathRef);
    378     this->resetFields();
    379 }
    380 
    381 bool SkPath::isEmpty() const {
    382     SkDEBUGCODE(this->validate();)
    383     return 0 == fPathRef->countVerbs();
    384 }
    385 
    386 bool SkPath::isLine(SkPoint line[2]) const {
    387     int verbCount = fPathRef->countVerbs();
    388 
    389     if (2 == verbCount) {
    390         SkASSERT(kMove_Verb == fPathRef->atVerb(0));
    391         if (kLine_Verb == fPathRef->atVerb(1)) {
    392             SkASSERT(2 == fPathRef->countPoints());
    393             if (line) {
    394                 const SkPoint* pts = fPathRef->points();
    395                 line[0] = pts[0];
    396                 line[1] = pts[1];
    397             }
    398             return true;
    399         }
    400     }
    401     return false;
    402 }
    403 
    404 /*
    405  Determines if path is a rect by keeping track of changes in direction
    406  and looking for a loop either clockwise or counterclockwise.
    407 
    408  The direction is computed such that:
    409   0: vertical up
    410   1: horizontal left
    411   2: vertical down
    412   3: horizontal right
    413 
    414 A rectangle cycles up/right/down/left or up/left/down/right.
    415 
    416 The test fails if:
    417   The path is closed, and followed by a line.
    418   A second move creates a new endpoint.
    419   A diagonal line is parsed.
    420   There's more than four changes of direction.
    421   There's a discontinuity on the line (e.g., a move in the middle)
    422   The line reverses direction.
    423   The rectangle doesn't complete a cycle.
    424   The path contains a quadratic or cubic.
    425   The path contains fewer than four points.
    426   The final point isn't equal to the first point.
    427 
    428 It's OK if the path has:
    429   Several colinear line segments composing a rectangle side.
    430   Single points on the rectangle side.
    431 
    432 The direction takes advantage of the corners found since opposite sides
    433 must travel in opposite directions.
    434 
    435 FIXME: Allow colinear quads and cubics to be treated like lines.
    436 FIXME: If the API passes fill-only, return true if the filled stroke
    437        is a rectangle, though the caller failed to close the path.
    438  */
    439 bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr,
    440         bool* isClosed, Direction* direction) const {
    441     int corners = 0;
    442     SkPoint first, last;
    443     const SkPoint* pts = *ptsPtr;
    444     const SkPoint* savePts = NULL;
    445     first.set(0, 0);
    446     last.set(0, 0);
    447     int firstDirection = 0;
    448     int lastDirection = 0;
    449     int nextDirection = 0;
    450     bool closedOrMoved = false;
    451     bool autoClose = false;
    452     int verbCnt = fPathRef->countVerbs();
    453     while (*currVerb < verbCnt && (!allowPartial || !autoClose)) {
    454         switch (fPathRef->atVerb(*currVerb)) {
    455             case kClose_Verb:
    456                 savePts = pts;
    457                 pts = *ptsPtr;
    458                 autoClose = true;
    459             case kLine_Verb: {
    460                 SkScalar left = last.fX;
    461                 SkScalar top = last.fY;
    462                 SkScalar right = pts->fX;
    463                 SkScalar bottom = pts->fY;
    464                 ++pts;
    465                 if (left != right && top != bottom) {
    466                     return false; // diagonal
    467                 }
    468                 if (left == right && top == bottom) {
    469                     break; // single point on side OK
    470                 }
    471                 nextDirection = (left != right) << 0 |
    472                     (left < right || top < bottom) << 1;
    473                 if (0 == corners) {
    474                     firstDirection = nextDirection;
    475                     first = last;
    476                     last = pts[-1];
    477                     corners = 1;
    478                     closedOrMoved = false;
    479                     break;
    480                 }
    481                 if (closedOrMoved) {
    482                     return false; // closed followed by a line
    483                 }
    484                 if (autoClose && nextDirection == firstDirection) {
    485                     break; // colinear with first
    486                 }
    487                 closedOrMoved = autoClose;
    488                 if (lastDirection != nextDirection) {
    489                     if (++corners > 4) {
    490                         return false; // too many direction changes
    491                     }
    492                 }
    493                 last = pts[-1];
    494                 if (lastDirection == nextDirection) {
    495                     break; // colinear segment
    496                 }
    497                 // Possible values for corners are 2, 3, and 4.
    498                 // When corners == 3, nextDirection opposes firstDirection.
    499                 // Otherwise, nextDirection at corner 2 opposes corner 4.
    500                 int turn = firstDirection ^ (corners - 1);
    501                 int directionCycle = 3 == corners ? 0 : nextDirection ^ turn;
    502                 if ((directionCycle ^ turn) != nextDirection) {
    503                     return false; // direction didn't follow cycle
    504                 }
    505                 break;
    506             }
    507             case kQuad_Verb:
    508             case kConic_Verb:
    509             case kCubic_Verb:
    510                 return false; // quadratic, cubic not allowed
    511             case kMove_Verb:
    512                 last = *pts++;
    513                 closedOrMoved = true;
    514                 break;
    515             default:
    516                 SkASSERT(!"unexpected verb");
    517                 break;
    518         }
    519         *currVerb += 1;
    520         lastDirection = nextDirection;
    521     }
    522     // Success if 4 corners and first point equals last
    523     bool result = 4 == corners && (first == last || autoClose);
    524     if (savePts) {
    525         *ptsPtr = savePts;
    526     }
    527     if (result && isClosed) {
    528         *isClosed = autoClose;
    529     }
    530     if (result && direction) {
    531         *direction = firstDirection == ((lastDirection + 1) & 3) ? kCCW_Direction : kCW_Direction;
    532     }
    533     return result;
    534 }
    535 
    536 bool SkPath::isRect(SkRect* rect) const {
    537     SkDEBUGCODE(this->validate();)
    538     int currVerb = 0;
    539     const SkPoint* pts = fPathRef->points();
    540     bool result = isRectContour(false, &currVerb, &pts, NULL, NULL);
    541     if (result && rect) {
    542         *rect = getBounds();
    543     }
    544     return result;
    545 }
    546 
    547 bool SkPath::isRect(bool* isClosed, Direction* direction) const {
    548     SkDEBUGCODE(this->validate();)
    549     int currVerb = 0;
    550     const SkPoint* pts = fPathRef->points();
    551     return isRectContour(false, &currVerb, &pts, isClosed, direction);
    552 }
    553 
    554 bool SkPath::isNestedRects(SkRect rects[2], Direction dirs[2]) const {
    555     SkDEBUGCODE(this->validate();)
    556     int currVerb = 0;
    557     const SkPoint* pts = fPathRef->points();
    558     const SkPoint* first = pts;
    559     Direction testDirs[2];
    560     if (!isRectContour(true, &currVerb, &pts, NULL, &testDirs[0])) {
    561         return false;
    562     }
    563     const SkPoint* last = pts;
    564     SkRect testRects[2];
    565     if (isRectContour(false, &currVerb, &pts, NULL, &testDirs[1])) {
    566         testRects[0].set(first, SkToS32(last - first));
    567         testRects[1].set(last, SkToS32(pts - last));
    568         if (testRects[0].contains(testRects[1])) {
    569             if (rects) {
    570                 rects[0] = testRects[0];
    571                 rects[1] = testRects[1];
    572             }
    573             if (dirs) {
    574                 dirs[0] = testDirs[0];
    575                 dirs[1] = testDirs[1];
    576             }
    577             return true;
    578         }
    579         if (testRects[1].contains(testRects[0])) {
    580             if (rects) {
    581                 rects[0] = testRects[1];
    582                 rects[1] = testRects[0];
    583             }
    584             if (dirs) {
    585                 dirs[0] = testDirs[1];
    586                 dirs[1] = testDirs[0];
    587             }
    588             return true;
    589         }
    590     }
    591     return false;
    592 }
    593 
    594 int SkPath::countPoints() const {
    595     return fPathRef->countPoints();
    596 }
    597 
    598 int SkPath::getPoints(SkPoint dst[], int max) const {
    599     SkDEBUGCODE(this->validate();)
    600 
    601     SkASSERT(max >= 0);
    602     SkASSERT(!max || dst);
    603     int count = SkMin32(max, fPathRef->countPoints());
    604     memcpy(dst, fPathRef->points(), count * sizeof(SkPoint));
    605     return fPathRef->countPoints();
    606 }
    607 
    608 SkPoint SkPath::getPoint(int index) const {
    609     if ((unsigned)index < (unsigned)fPathRef->countPoints()) {
    610         return fPathRef->atPoint(index);
    611     }
    612     return SkPoint::Make(0, 0);
    613 }
    614 
    615 int SkPath::countVerbs() const {
    616     return fPathRef->countVerbs();
    617 }
    618 
    619 static inline void copy_verbs_reverse(uint8_t* inorderDst,
    620                                       const uint8_t* reversedSrc,
    621                                       int count) {
    622     for (int i = 0; i < count; ++i) {
    623         inorderDst[i] = reversedSrc[~i];
    624     }
    625 }
    626 
    627 int SkPath::getVerbs(uint8_t dst[], int max) const {
    628     SkDEBUGCODE(this->validate();)
    629 
    630     SkASSERT(max >= 0);
    631     SkASSERT(!max || dst);
    632     int count = SkMin32(max, fPathRef->countVerbs());
    633     copy_verbs_reverse(dst, fPathRef->verbs(), count);
    634     return fPathRef->countVerbs();
    635 }
    636 
    637 bool SkPath::getLastPt(SkPoint* lastPt) const {
    638     SkDEBUGCODE(this->validate();)
    639 
    640     int count = fPathRef->countPoints();
    641     if (count > 0) {
    642         if (lastPt) {
    643             *lastPt = fPathRef->atPoint(count - 1);
    644         }
    645         return true;
    646     }
    647     if (lastPt) {
    648         lastPt->set(0, 0);
    649     }
    650     return false;
    651 }
    652 
    653 void SkPath::setLastPt(SkScalar x, SkScalar y) {
    654     SkDEBUGCODE(this->validate();)
    655 
    656     int count = fPathRef->countPoints();
    657     if (count == 0) {
    658         this->moveTo(x, y);
    659     } else {
    660         fIsOval = false;
    661         SkPathRef::Editor ed(&fPathRef);
    662         ed.atPoint(count-1)->set(x, y);
    663         GEN_ID_INC;
    664     }
    665 }
    666 
    667 void SkPath::computeBounds() const {
    668     SkDEBUGCODE(this->validate();)
    669     SkASSERT(fBoundsIsDirty);
    670 
    671     fIsFinite = compute_pt_bounds(&fBounds, *fPathRef.get());
    672     fBoundsIsDirty = false;
    673 }
    674 
    675 void SkPath::setConvexity(Convexity c) {
    676     if (fConvexity != c) {
    677         fConvexity = c;
    678         GEN_ID_INC;
    679     }
    680 }
    681 
    682 //////////////////////////////////////////////////////////////////////////////
    683 //  Construction methods
    684 
    685 #define DIRTY_AFTER_EDIT                 \
    686     do {                                 \
    687         fBoundsIsDirty = true;           \
    688         fConvexity = kUnknown_Convexity; \
    689         fDirection = kUnknown_Direction; \
    690         fIsOval = false;                 \
    691     } while (0)
    692 
    693 #define DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE   \
    694     do {                                                    \
    695         fBoundsIsDirty = true;                              \
    696     } while (0)
    697 
    698 void SkPath::incReserve(U16CPU inc) {
    699     SkDEBUGCODE(this->validate();)
    700     SkPathRef::Editor(&fPathRef, inc, inc);
    701     SkDEBUGCODE(this->validate();)
    702 }
    703 
    704 void SkPath::moveTo(SkScalar x, SkScalar y) {
    705     SkDEBUGCODE(this->validate();)
    706 
    707     SkPathRef::Editor ed(&fPathRef);
    708 
    709     // remember our index
    710     fLastMoveToIndex = ed.pathRef()->countPoints();
    711 
    712     ed.growForVerb(kMove_Verb)->set(x, y);
    713 
    714     GEN_ID_INC;
    715     DIRTY_AFTER_EDIT_NO_CONVEXITY_OR_DIRECTION_CHANGE;
    716 }
    717 
    718 void SkPath::rMoveTo(SkScalar x, SkScalar y) {
    719     SkPoint pt;
    720     this->getLastPt(&pt);
    721     this->moveTo(pt.fX + x, pt.fY + y);
    722 }
    723 
    724 void SkPath::injectMoveToIfNeeded() {
    725     if (fLastMoveToIndex < 0) {
    726         SkScalar x, y;
    727         if (fPathRef->countVerbs() == 0) {
    728             x = y = 0;
    729         } else {
    730             const SkPoint& pt = fPathRef->atPoint(~fLastMoveToIndex);
    731             x = pt.fX;
    732             y = pt.fY;
    733         }
    734         this->moveTo(x, y);
    735     }
    736 }
    737 
    738 void SkPath::lineTo(SkScalar x, SkScalar y) {
    739     SkDEBUGCODE(this->validate();)
    740 
    741     this->injectMoveToIfNeeded();
    742 
    743     SkPathRef::Editor ed(&fPathRef);
    744     ed.growForVerb(kLine_Verb)->set(x, y);
    745     fSegmentMask |= kLine_SegmentMask;
    746 
    747     GEN_ID_INC;
    748     DIRTY_AFTER_EDIT;
    749 }
    750 
    751 void SkPath::rLineTo(SkScalar x, SkScalar y) {
    752     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
    753     SkPoint pt;
    754     this->getLastPt(&pt);
    755     this->lineTo(pt.fX + x, pt.fY + y);
    756 }
    757 
    758 void SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
    759     SkDEBUGCODE(this->validate();)
    760 
    761     this->injectMoveToIfNeeded();
    762 
    763     SkPathRef::Editor ed(&fPathRef);
    764     SkPoint* pts = ed.growForVerb(kQuad_Verb);
    765     pts[0].set(x1, y1);
    766     pts[1].set(x2, y2);
    767     fSegmentMask |= kQuad_SegmentMask;
    768 
    769     GEN_ID_INC;
    770     DIRTY_AFTER_EDIT;
    771 }
    772 
    773 void SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
    774     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
    775     SkPoint pt;
    776     this->getLastPt(&pt);
    777     this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2);
    778 }
    779 
    780 void SkPath::conicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    781                      SkScalar w) {
    782     // check for <= 0 or NaN with this test
    783     if (!(w > 0)) {
    784         this->lineTo(x2, y2);
    785     } else if (!SkScalarIsFinite(w)) {
    786         this->lineTo(x1, y1);
    787         this->lineTo(x2, y2);
    788     } else if (SK_Scalar1 == w) {
    789         this->quadTo(x1, y1, x2, y2);
    790     } else {
    791         SkDEBUGCODE(this->validate();)
    792 
    793         this->injectMoveToIfNeeded();
    794 
    795         SkPathRef::Editor ed(&fPathRef);
    796         SkPoint* pts = ed.growForConic(w);
    797         pts[0].set(x1, y1);
    798         pts[1].set(x2, y2);
    799         fSegmentMask |= kConic_SegmentMask;
    800 
    801         GEN_ID_INC;
    802         DIRTY_AFTER_EDIT;
    803     }
    804 }
    805 
    806 void SkPath::rConicTo(SkScalar dx1, SkScalar dy1, SkScalar dx2, SkScalar dy2,
    807                       SkScalar w) {
    808     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
    809     SkPoint pt;
    810     this->getLastPt(&pt);
    811     this->conicTo(pt.fX + dx1, pt.fY + dy1, pt.fX + dx2, pt.fY + dy2, w);
    812 }
    813 
    814 void SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    815                      SkScalar x3, SkScalar y3) {
    816     SkDEBUGCODE(this->validate();)
    817 
    818     this->injectMoveToIfNeeded();
    819 
    820     SkPathRef::Editor ed(&fPathRef);
    821     SkPoint* pts = ed.growForVerb(kCubic_Verb);
    822     pts[0].set(x1, y1);
    823     pts[1].set(x2, y2);
    824     pts[2].set(x3, y3);
    825     fSegmentMask |= kCubic_SegmentMask;
    826 
    827     GEN_ID_INC;
    828     DIRTY_AFTER_EDIT;
    829 }
    830 
    831 void SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
    832                       SkScalar x3, SkScalar y3) {
    833     this->injectMoveToIfNeeded();  // This can change the result of this->getLastPt().
    834     SkPoint pt;
    835     this->getLastPt(&pt);
    836     this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2,
    837                   pt.fX + x3, pt.fY + y3);
    838 }
    839 
    840 void SkPath::close() {
    841     SkDEBUGCODE(this->validate();)
    842 
    843     int count = fPathRef->countVerbs();
    844     if (count > 0) {
    845         switch (fPathRef->atVerb(count - 1)) {
    846             case kLine_Verb:
    847             case kQuad_Verb:
    848             case kConic_Verb:
    849             case kCubic_Verb:
    850             case kMove_Verb: {
    851                 SkPathRef::Editor ed(&fPathRef);
    852                 ed.growForVerb(kClose_Verb);
    853                 GEN_ID_INC;
    854                 break;
    855             }
    856             case kClose_Verb:
    857                 // don't add a close if it's the first verb or a repeat
    858                 break;
    859             default:
    860                 SkASSERT(!"unexpected verb");
    861                 break;
    862         }
    863     }
    864 
    865     // signal that we need a moveTo to follow us (unless we're done)
    866 #if 0
    867     if (fLastMoveToIndex >= 0) {
    868         fLastMoveToIndex = ~fLastMoveToIndex;
    869     }
    870 #else
    871     fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
    872 #endif
    873 }
    874 
    875 ///////////////////////////////////////////////////////////////////////////////
    876 
    877 static void assert_known_direction(int dir) {
    878     SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir);
    879 }
    880 
    881 void SkPath::addRect(const SkRect& rect, Direction dir) {
    882     this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir);
    883 }
    884 
    885 void SkPath::addRect(SkScalar left, SkScalar top, SkScalar right,
    886                      SkScalar bottom, Direction dir) {
    887     assert_known_direction(dir);
    888     fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction;
    889     SkAutoDisableDirectionCheck addc(this);
    890 
    891     SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom);
    892 
    893     this->incReserve(5);
    894 
    895     this->moveTo(left, top);
    896     if (dir == kCCW_Direction) {
    897         this->lineTo(left, bottom);
    898         this->lineTo(right, bottom);
    899         this->lineTo(right, top);
    900     } else {
    901         this->lineTo(right, top);
    902         this->lineTo(right, bottom);
    903         this->lineTo(left, bottom);
    904     }
    905     this->close();
    906 }
    907 
    908 void SkPath::addPoly(const SkPoint pts[], int count, bool close) {
    909     SkDEBUGCODE(this->validate();)
    910     if (count <= 0) {
    911         return;
    912     }
    913 
    914     SkPathRef::Editor ed(&fPathRef);
    915     fLastMoveToIndex = ed.pathRef()->countPoints();
    916     uint8_t* vb;
    917     SkPoint* p;
    918     // +close makes room for the extra kClose_Verb
    919     ed.grow(count + close, count, &vb, &p);
    920 
    921     memcpy(p, pts, count * sizeof(SkPoint));
    922     vb[~0] = kMove_Verb;
    923     if (count > 1) {
    924         // cast to unsigned, so if MIN_COUNT_FOR_MEMSET_TO_BE_FAST is defined to
    925         // be 0, the compiler will remove the test/branch entirely.
    926         if ((unsigned)count >= MIN_COUNT_FOR_MEMSET_TO_BE_FAST) {
    927             memset(vb - count, kLine_Verb, count - 1);
    928         } else {
    929             for (int i = 1; i < count; ++i) {
    930                 vb[~i] = kLine_Verb;
    931             }
    932         }
    933         fSegmentMask |= kLine_SegmentMask;
    934     }
    935     if (close) {
    936         vb[~count] = kClose_Verb;
    937     }
    938 
    939     GEN_ID_INC;
    940     DIRTY_AFTER_EDIT;
    941     SkDEBUGCODE(this->validate();)
    942 }
    943 
    944 static void add_corner_arc(SkPath* path, const SkRect& rect,
    945                            SkScalar rx, SkScalar ry, int startAngle,
    946                            SkPath::Direction dir, bool forceMoveTo) {
    947     // These two asserts are not sufficient, since really we want to know
    948     // that the pair of radii (e.g. left and right, or top and bottom) sum
    949     // to <= dimension, but we don't have that data here, so we just have
    950     // these conservative asserts.
    951     SkASSERT(0 <= rx && rx <= rect.width());
    952     SkASSERT(0 <= ry && ry <= rect.height());
    953 
    954     SkRect   r;
    955     r.set(-rx, -ry, rx, ry);
    956 
    957     switch (startAngle) {
    958         case   0:
    959             r.offset(rect.fRight - r.fRight, rect.fBottom - r.fBottom);
    960             break;
    961         case  90:
    962             r.offset(rect.fLeft - r.fLeft,   rect.fBottom - r.fBottom);
    963             break;
    964         case 180: r.offset(rect.fLeft - r.fLeft,   rect.fTop - r.fTop); break;
    965         case 270: r.offset(rect.fRight - r.fRight, rect.fTop - r.fTop); break;
    966         default: SkDEBUGFAIL("unexpected startAngle in add_corner_arc");
    967     }
    968 
    969     SkScalar start = SkIntToScalar(startAngle);
    970     SkScalar sweep = SkIntToScalar(90);
    971     if (SkPath::kCCW_Direction == dir) {
    972         start += sweep;
    973         sweep = -sweep;
    974     }
    975 
    976     path->arcTo(r, start, sweep, forceMoveTo);
    977 }
    978 
    979 void SkPath::addRoundRect(const SkRect& rect, const SkScalar radii[],
    980                           Direction dir) {
    981     SkRRect rrect;
    982     rrect.setRectRadii(rect, (const SkVector*) radii);
    983     this->addRRect(rrect, dir);
    984 }
    985 
    986 void SkPath::addRRect(const SkRRect& rrect, Direction dir) {
    987     assert_known_direction(dir);
    988 
    989     if (rrect.isEmpty()) {
    990         return;
    991     }
    992 
    993     const SkRect& bounds = rrect.getBounds();
    994 
    995     if (rrect.isRect()) {
    996         this->addRect(bounds, dir);
    997     } else if (rrect.isOval()) {
    998         this->addOval(bounds, dir);
    999     } else if (rrect.isSimple()) {
   1000         const SkVector& rad = rrect.getSimpleRadii();
   1001         this->addRoundRect(bounds, rad.x(), rad.y(), dir);
   1002     } else {
   1003         SkAutoPathBoundsUpdate apbu(this, bounds);
   1004 
   1005         if (kCW_Direction == dir) {
   1006             add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true);
   1007             add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false);
   1008             add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY,   0, dir, false);
   1009             add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY,  90, dir, false);
   1010         } else {
   1011             add_corner_arc(this, bounds, rrect.fRadii[0].fX, rrect.fRadii[0].fY, 180, dir, true);
   1012             add_corner_arc(this, bounds, rrect.fRadii[3].fX, rrect.fRadii[3].fY,  90, dir, false);
   1013             add_corner_arc(this, bounds, rrect.fRadii[2].fX, rrect.fRadii[2].fY,   0, dir, false);
   1014             add_corner_arc(this, bounds, rrect.fRadii[1].fX, rrect.fRadii[1].fY, 270, dir, false);
   1015         }
   1016         this->close();
   1017     }
   1018 }
   1019 
   1020 bool SkPath::hasOnlyMoveTos() const {
   1021     int count = fPathRef->countVerbs();
   1022     const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbsMemBegin();
   1023     for (int i = 0; i < count; ++i) {
   1024         if (*verbs == kLine_Verb ||
   1025             *verbs == kQuad_Verb ||
   1026             *verbs == kCubic_Verb) {
   1027             return false;
   1028         }
   1029         ++verbs;
   1030     }
   1031     return true;
   1032 }
   1033 
   1034 #define CUBIC_ARC_FACTOR    ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3)
   1035 
   1036 void SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry,
   1037                           Direction dir) {
   1038     assert_known_direction(dir);
   1039 
   1040     if (rx < 0 || ry < 0) {
   1041         SkErrorInternals::SetError( kInvalidArgument_SkError,
   1042                                     "I got %f and %f as radii to SkPath::AddRoundRect, "
   1043                                     "but negative radii are not allowed.",
   1044                                     SkScalarToDouble(rx), SkScalarToDouble(ry) );
   1045         return;
   1046     }
   1047 
   1048     SkScalar    w = rect.width();
   1049     SkScalar    halfW = SkScalarHalf(w);
   1050     SkScalar    h = rect.height();
   1051     SkScalar    halfH = SkScalarHalf(h);
   1052 
   1053     if (halfW <= 0 || halfH <= 0) {
   1054         return;
   1055     }
   1056 
   1057     bool skip_hori = rx >= halfW;
   1058     bool skip_vert = ry >= halfH;
   1059 
   1060     if (skip_hori && skip_vert) {
   1061         this->addOval(rect, dir);
   1062         return;
   1063     }
   1064 
   1065     fDirection = this->hasOnlyMoveTos() ? dir : kUnknown_Direction;
   1066 
   1067     SkAutoPathBoundsUpdate apbu(this, rect);
   1068     SkAutoDisableDirectionCheck(this);
   1069 
   1070     if (skip_hori) {
   1071         rx = halfW;
   1072     } else if (skip_vert) {
   1073         ry = halfH;
   1074     }
   1075 
   1076     SkScalar    sx = SkScalarMul(rx, CUBIC_ARC_FACTOR);
   1077     SkScalar    sy = SkScalarMul(ry, CUBIC_ARC_FACTOR);
   1078 
   1079     this->incReserve(17);
   1080     this->moveTo(rect.fRight - rx, rect.fTop);
   1081     if (dir == kCCW_Direction) {
   1082         if (!skip_hori) {
   1083             this->lineTo(rect.fLeft + rx, rect.fTop);       // top
   1084         }
   1085         this->cubicTo(rect.fLeft + rx - sx, rect.fTop,
   1086                       rect.fLeft, rect.fTop + ry - sy,
   1087                       rect.fLeft, rect.fTop + ry);          // top-left
   1088         if (!skip_vert) {
   1089             this->lineTo(rect.fLeft, rect.fBottom - ry);        // left
   1090         }
   1091         this->cubicTo(rect.fLeft, rect.fBottom - ry + sy,
   1092                       rect.fLeft + rx - sx, rect.fBottom,
   1093                       rect.fLeft + rx, rect.fBottom);       // bot-left
   1094         if (!skip_hori) {
   1095             this->lineTo(rect.fRight - rx, rect.fBottom);   // bottom
   1096         }
   1097         this->cubicTo(rect.fRight - rx + sx, rect.fBottom,
   1098                       rect.fRight, rect.fBottom - ry + sy,
   1099                       rect.fRight, rect.fBottom - ry);      // bot-right
   1100         if (!skip_vert) {
   1101             this->lineTo(rect.fRight, rect.fTop + ry);
   1102         }
   1103         this->cubicTo(rect.fRight, rect.fTop + ry - sy,
   1104                       rect.fRight - rx + sx, rect.fTop,
   1105                       rect.fRight - rx, rect.fTop);         // top-right
   1106     } else {
   1107         this->cubicTo(rect.fRight - rx + sx, rect.fTop,
   1108                       rect.fRight, rect.fTop + ry - sy,
   1109                       rect.fRight, rect.fTop + ry);         // top-right
   1110         if (!skip_vert) {
   1111             this->lineTo(rect.fRight, rect.fBottom - ry);
   1112         }
   1113         this->cubicTo(rect.fRight, rect.fBottom - ry + sy,
   1114                       rect.fRight - rx + sx, rect.fBottom,
   1115                       rect.fRight - rx, rect.fBottom);      // bot-right
   1116         if (!skip_hori) {
   1117             this->lineTo(rect.fLeft + rx, rect.fBottom);    // bottom
   1118         }
   1119         this->cubicTo(rect.fLeft + rx - sx, rect.fBottom,
   1120                       rect.fLeft, rect.fBottom - ry + sy,
   1121                       rect.fLeft, rect.fBottom - ry);       // bot-left
   1122         if (!skip_vert) {
   1123             this->lineTo(rect.fLeft, rect.fTop + ry);       // left
   1124         }
   1125         this->cubicTo(rect.fLeft, rect.fTop + ry - sy,
   1126                       rect.fLeft + rx - sx, rect.fTop,
   1127                       rect.fLeft + rx, rect.fTop);          // top-left
   1128         if (!skip_hori) {
   1129             this->lineTo(rect.fRight - rx, rect.fTop);      // top
   1130         }
   1131     }
   1132     this->close();
   1133 }
   1134 
   1135 void SkPath::addOval(const SkRect& oval, Direction dir) {
   1136     assert_known_direction(dir);
   1137 
   1138     /* If addOval() is called after previous moveTo(),
   1139        this path is still marked as an oval. This is used to
   1140        fit into WebKit's calling sequences.
   1141        We can't simply check isEmpty() in this case, as additional
   1142        moveTo() would mark the path non empty.
   1143      */
   1144     fIsOval = hasOnlyMoveTos();
   1145     if (fIsOval) {
   1146         fDirection = dir;
   1147     } else {
   1148         fDirection = kUnknown_Direction;
   1149     }
   1150 
   1151     SkAutoDisableOvalCheck adoc(this);
   1152     SkAutoDisableDirectionCheck addc(this);
   1153 
   1154     SkAutoPathBoundsUpdate apbu(this, oval);
   1155 
   1156     SkScalar    cx = oval.centerX();
   1157     SkScalar    cy = oval.centerY();
   1158     SkScalar    rx = SkScalarHalf(oval.width());
   1159     SkScalar    ry = SkScalarHalf(oval.height());
   1160 
   1161     SkScalar    sx = SkScalarMul(rx, SK_ScalarTanPIOver8);
   1162     SkScalar    sy = SkScalarMul(ry, SK_ScalarTanPIOver8);
   1163     SkScalar    mx = SkScalarMul(rx, SK_ScalarRoot2Over2);
   1164     SkScalar    my = SkScalarMul(ry, SK_ScalarRoot2Over2);
   1165 
   1166     /*
   1167         To handle imprecision in computing the center and radii, we revert to
   1168         the provided bounds when we can (i.e. use oval.fLeft instead of cx-rx)
   1169         to ensure that we don't exceed the oval's bounds *ever*, since we want
   1170         to use oval for our fast-bounds, rather than have to recompute it.
   1171     */
   1172     const SkScalar L = oval.fLeft;      // cx - rx
   1173     const SkScalar T = oval.fTop;       // cy - ry
   1174     const SkScalar R = oval.fRight;     // cx + rx
   1175     const SkScalar B = oval.fBottom;    // cy + ry
   1176 
   1177     this->incReserve(17);   // 8 quads + close
   1178     this->moveTo(R, cy);
   1179     if (dir == kCCW_Direction) {
   1180         this->quadTo(      R, cy - sy, cx + mx, cy - my);
   1181         this->quadTo(cx + sx,       T, cx     ,       T);
   1182         this->quadTo(cx - sx,       T, cx - mx, cy - my);
   1183         this->quadTo(      L, cy - sy,       L, cy     );
   1184         this->quadTo(      L, cy + sy, cx - mx, cy + my);
   1185         this->quadTo(cx - sx,       B, cx     ,       B);
   1186         this->quadTo(cx + sx,       B, cx + mx, cy + my);
   1187         this->quadTo(      R, cy + sy,       R, cy     );
   1188     } else {
   1189         this->quadTo(      R, cy + sy, cx + mx, cy + my);
   1190         this->quadTo(cx + sx,       B, cx     ,       B);
   1191         this->quadTo(cx - sx,       B, cx - mx, cy + my);
   1192         this->quadTo(      L, cy + sy,       L, cy     );
   1193         this->quadTo(      L, cy - sy, cx - mx, cy - my);
   1194         this->quadTo(cx - sx,       T, cx     ,       T);
   1195         this->quadTo(cx + sx,       T, cx + mx, cy - my);
   1196         this->quadTo(      R, cy - sy,       R, cy     );
   1197     }
   1198     this->close();
   1199 }
   1200 
   1201 bool SkPath::isOval(SkRect* rect) const {
   1202     if (fIsOval && rect) {
   1203         *rect = getBounds();
   1204     }
   1205 
   1206     return fIsOval;
   1207 }
   1208 
   1209 void SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) {
   1210     if (r > 0) {
   1211         SkRect  rect;
   1212         rect.set(x - r, y - r, x + r, y + r);
   1213         this->addOval(rect, dir);
   1214     }
   1215 }
   1216 
   1217 #include "SkGeometry.h"
   1218 
   1219 static int build_arc_points(const SkRect& oval, SkScalar startAngle,
   1220                             SkScalar sweepAngle,
   1221                             SkPoint pts[kSkBuildQuadArcStorage]) {
   1222 
   1223     if (0 == sweepAngle &&
   1224         (0 == startAngle || SkIntToScalar(360) == startAngle)) {
   1225         // Chrome uses this path to move into and out of ovals. If not
   1226         // treated as a special case the moves can distort the oval's
   1227         // bounding box (and break the circle special case).
   1228         pts[0].set(oval.fRight, oval.centerY());
   1229         return 1;
   1230     } else if (0 == oval.width() && 0 == oval.height()) {
   1231         // Chrome will sometimes create 0 radius round rects. Having degenerate
   1232         // quad segments in the path prevents the path from being recognized as
   1233         // a rect.
   1234         // TODO: optimizing the case where only one of width or height is zero
   1235         // should also be considered. This case, however, doesn't seem to be
   1236         // as common as the single point case.
   1237         pts[0].set(oval.fRight, oval.fTop);
   1238         return 1;
   1239     }
   1240 
   1241     SkVector start, stop;
   1242 
   1243     start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX);
   1244     stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle),
   1245                              &stop.fX);
   1246 
   1247     /*  If the sweep angle is nearly (but less than) 360, then due to precision
   1248         loss in radians-conversion and/or sin/cos, we may end up with coincident
   1249         vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead
   1250         of drawing a nearly complete circle (good).
   1251              e.g. canvas.drawArc(0, 359.99, ...)
   1252              -vs- canvas.drawArc(0, 359.9, ...)
   1253         We try to detect this edge case, and tweak the stop vector
   1254      */
   1255     if (start == stop) {
   1256         SkScalar sw = SkScalarAbs(sweepAngle);
   1257         if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) {
   1258             SkScalar stopRad = SkDegreesToRadians(startAngle + sweepAngle);
   1259             // make a guess at a tiny angle (in radians) to tweak by
   1260             SkScalar deltaRad = SkScalarCopySign(SK_Scalar1/512, sweepAngle);
   1261             // not sure how much will be enough, so we use a loop
   1262             do {
   1263                 stopRad -= deltaRad;
   1264                 stop.fY = SkScalarSinCos(stopRad, &stop.fX);
   1265             } while (start == stop);
   1266         }
   1267     }
   1268 
   1269     SkMatrix    matrix;
   1270 
   1271     matrix.setScale(SkScalarHalf(oval.width()), SkScalarHalf(oval.height()));
   1272     matrix.postTranslate(oval.centerX(), oval.centerY());
   1273 
   1274     return SkBuildQuadArc(start, stop,
   1275           sweepAngle > 0 ? kCW_SkRotationDirection : kCCW_SkRotationDirection,
   1276                           &matrix, pts);
   1277 }
   1278 
   1279 void SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
   1280                    bool forceMoveTo) {
   1281     if (oval.width() < 0 || oval.height() < 0) {
   1282         return;
   1283     }
   1284 
   1285     SkPoint pts[kSkBuildQuadArcStorage];
   1286     int count = build_arc_points(oval, startAngle, sweepAngle, pts);
   1287     SkASSERT((count & 1) == 1);
   1288 
   1289     if (fPathRef->countVerbs() == 0) {
   1290         forceMoveTo = true;
   1291     }
   1292     this->incReserve(count);
   1293     forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]);
   1294     for (int i = 1; i < count; i += 2) {
   1295         this->quadTo(pts[i], pts[i+1]);
   1296     }
   1297 }
   1298 
   1299 void SkPath::addArc(const SkRect& oval, SkScalar startAngle,
   1300                     SkScalar sweepAngle) {
   1301     if (oval.isEmpty() || 0 == sweepAngle) {
   1302         return;
   1303     }
   1304 
   1305     const SkScalar kFullCircleAngle = SkIntToScalar(360);
   1306 
   1307     if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) {
   1308         this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction);
   1309         return;
   1310     }
   1311 
   1312     SkPoint pts[kSkBuildQuadArcStorage];
   1313     int count = build_arc_points(oval, startAngle, sweepAngle, pts);
   1314 
   1315     this->incReserve(count);
   1316     this->moveTo(pts[0]);
   1317     for (int i = 1; i < count; i += 2) {
   1318         this->quadTo(pts[i], pts[i+1]);
   1319     }
   1320 }
   1321 
   1322 /*
   1323     Need to handle the case when the angle is sharp, and our computed end-points
   1324     for the arc go behind pt1 and/or p2...
   1325 */
   1326 void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
   1327                    SkScalar radius) {
   1328     SkVector    before, after;
   1329 
   1330     // need to know our prev pt so we can construct tangent vectors
   1331     {
   1332         SkPoint start;
   1333         this->getLastPt(&start);
   1334         // Handle degenerate cases by adding a line to the first point and
   1335         // bailing out.
   1336         if ((x1 == start.fX && y1 == start.fY) ||
   1337             (x1 == x2 && y1 == y2) ||
   1338             radius == 0) {
   1339             this->lineTo(x1, y1);
   1340             return;
   1341         }
   1342         before.setNormalize(x1 - start.fX, y1 - start.fY);
   1343         after.setNormalize(x2 - x1, y2 - y1);
   1344     }
   1345 
   1346     SkScalar cosh = SkPoint::DotProduct(before, after);
   1347     SkScalar sinh = SkPoint::CrossProduct(before, after);
   1348 
   1349     if (SkScalarNearlyZero(sinh)) {   // angle is too tight
   1350         this->lineTo(x1, y1);
   1351         return;
   1352     }
   1353 
   1354     SkScalar dist = SkScalarMulDiv(radius, SK_Scalar1 - cosh, sinh);
   1355     if (dist < 0) {
   1356         dist = -dist;
   1357     }
   1358 
   1359     SkScalar xx = x1 - SkScalarMul(dist, before.fX);
   1360     SkScalar yy = y1 - SkScalarMul(dist, before.fY);
   1361     SkRotationDirection arcDir;
   1362 
   1363     // now turn before/after into normals
   1364     if (sinh > 0) {
   1365         before.rotateCCW();
   1366         after.rotateCCW();
   1367         arcDir = kCW_SkRotationDirection;
   1368     } else {
   1369         before.rotateCW();
   1370         after.rotateCW();
   1371         arcDir = kCCW_SkRotationDirection;
   1372     }
   1373 
   1374     SkMatrix    matrix;
   1375     SkPoint     pts[kSkBuildQuadArcStorage];
   1376 
   1377     matrix.setScale(radius, radius);
   1378     matrix.postTranslate(xx - SkScalarMul(radius, before.fX),
   1379                          yy - SkScalarMul(radius, before.fY));
   1380 
   1381     int count = SkBuildQuadArc(before, after, arcDir, &matrix, pts);
   1382 
   1383     this->incReserve(count);
   1384     // [xx,yy] == pts[0]
   1385     this->lineTo(xx, yy);
   1386     for (int i = 1; i < count; i += 2) {
   1387         this->quadTo(pts[i], pts[i+1]);
   1388     }
   1389 }
   1390 
   1391 ///////////////////////////////////////////////////////////////////////////////
   1392 
   1393 void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy) {
   1394     SkMatrix matrix;
   1395 
   1396     matrix.setTranslate(dx, dy);
   1397     this->addPath(path, matrix);
   1398 }
   1399 
   1400 void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
   1401     SkPathRef::Editor(&fPathRef, path.countVerbs(), path.countPoints());
   1402 
   1403     fIsOval = false;
   1404 
   1405     RawIter iter(path);
   1406     SkPoint pts[4];
   1407     Verb    verb;
   1408 
   1409     SkMatrix::MapPtsProc proc = matrix.getMapPtsProc();
   1410 
   1411     while ((verb = iter.next(pts)) != kDone_Verb) {
   1412         switch (verb) {
   1413             case kMove_Verb:
   1414                 proc(matrix, &pts[0], &pts[0], 1);
   1415                 this->moveTo(pts[0]);
   1416                 break;
   1417             case kLine_Verb:
   1418                 proc(matrix, &pts[1], &pts[1], 1);
   1419                 this->lineTo(pts[1]);
   1420                 break;
   1421             case kQuad_Verb:
   1422                 proc(matrix, &pts[1], &pts[1], 2);
   1423                 this->quadTo(pts[1], pts[2]);
   1424                 break;
   1425             case kConic_Verb:
   1426                 proc(matrix, &pts[1], &pts[1], 2);
   1427                 this->conicTo(pts[1], pts[2], iter.conicWeight());
   1428                 break;
   1429             case kCubic_Verb:
   1430                 proc(matrix, &pts[1], &pts[1], 3);
   1431                 this->cubicTo(pts[1], pts[2], pts[3]);
   1432                 break;
   1433             case kClose_Verb:
   1434                 this->close();
   1435                 break;
   1436             default:
   1437                 SkDEBUGFAIL("unknown verb");
   1438         }
   1439     }
   1440 }
   1441 
   1442 ///////////////////////////////////////////////////////////////////////////////
   1443 
   1444 static int pts_in_verb(unsigned verb) {
   1445     static const uint8_t gPtsInVerb[] = {
   1446         1,  // kMove
   1447         1,  // kLine
   1448         2,  // kQuad
   1449         2,  // kConic
   1450         3,  // kCubic
   1451         0,  // kClose
   1452         0   // kDone
   1453     };
   1454 
   1455     SkASSERT(verb < SK_ARRAY_COUNT(gPtsInVerb));
   1456     return gPtsInVerb[verb];
   1457 }
   1458 
   1459 // ignore the initial moveto, and stop when the 1st contour ends
   1460 void SkPath::pathTo(const SkPath& path) {
   1461     int i, vcount = path.fPathRef->countVerbs();
   1462     // exit early if the path is empty, or just has a moveTo.
   1463     if (vcount < 2) {
   1464         return;
   1465     }
   1466 
   1467     SkPathRef::Editor(&fPathRef, vcount, path.countPoints());
   1468 
   1469     fIsOval = false;
   1470 
   1471     const uint8_t* verbs = path.fPathRef->verbs();
   1472     // skip the initial moveTo
   1473     const SkPoint*  pts = path.fPathRef->points() + 1;
   1474     const SkScalar* conicWeight = path.fPathRef->conicWeights();
   1475 
   1476     SkASSERT(verbs[~0] == kMove_Verb);
   1477     for (i = 1; i < vcount; i++) {
   1478         switch (verbs[~i]) {
   1479             case kLine_Verb:
   1480                 this->lineTo(pts[0].fX, pts[0].fY);
   1481                 break;
   1482             case kQuad_Verb:
   1483                 this->quadTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY);
   1484                 break;
   1485             case kConic_Verb:
   1486                 this->conicTo(pts[0], pts[1], *conicWeight++);
   1487                 break;
   1488             case kCubic_Verb:
   1489                 this->cubicTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
   1490                 break;
   1491             case kClose_Verb:
   1492                 return;
   1493         }
   1494         pts += pts_in_verb(verbs[~i]);
   1495     }
   1496 }
   1497 
   1498 // ignore the last point of the 1st contour
   1499 void SkPath::reversePathTo(const SkPath& path) {
   1500     int i, vcount = path.fPathRef->countVerbs();
   1501     // exit early if the path is empty, or just has a moveTo.
   1502     if (vcount < 2) {
   1503         return;
   1504     }
   1505 
   1506     SkPathRef::Editor(&fPathRef, vcount, path.countPoints());
   1507 
   1508     fIsOval = false;
   1509 
   1510     const uint8_t*  verbs = path.fPathRef->verbs();
   1511     const SkPoint*  pts = path.fPathRef->points();
   1512     const SkScalar* conicWeights = path.fPathRef->conicWeights();
   1513 
   1514     SkASSERT(verbs[~0] == kMove_Verb);
   1515     for (i = 1; i < vcount; ++i) {
   1516         unsigned v = verbs[~i];
   1517         int n = pts_in_verb(v);
   1518         if (n == 0) {
   1519             break;
   1520         }
   1521         pts += n;
   1522         conicWeights += (SkPath::kConic_Verb == v);
   1523     }
   1524 
   1525     while (--i > 0) {
   1526         switch (verbs[~i]) {
   1527             case kLine_Verb:
   1528                 this->lineTo(pts[-1].fX, pts[-1].fY);
   1529                 break;
   1530             case kQuad_Verb:
   1531                 this->quadTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY);
   1532                 break;
   1533             case kConic_Verb:
   1534                 this->conicTo(pts[-1], pts[-2], *--conicWeights);
   1535                 break;
   1536             case kCubic_Verb:
   1537                 this->cubicTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY,
   1538                               pts[-3].fX, pts[-3].fY);
   1539                 break;
   1540             default:
   1541                 SkDEBUGFAIL("bad verb");
   1542                 break;
   1543         }
   1544         pts -= pts_in_verb(verbs[~i]);
   1545     }
   1546 }
   1547 
   1548 void SkPath::reverseAddPath(const SkPath& src) {
   1549     SkPathRef::Editor ed(&fPathRef, src.fPathRef->countPoints(), src.fPathRef->countVerbs());
   1550 
   1551     const SkPoint* pts = src.fPathRef->pointsEnd();
   1552     // we will iterator through src's verbs backwards
   1553     const uint8_t* verbs = src.fPathRef->verbsMemBegin(); // points at the last verb
   1554     const uint8_t* verbsEnd = src.fPathRef->verbs(); // points just past the first verb
   1555     const SkScalar* conicWeights = src.fPathRef->conicWeightsEnd();
   1556 
   1557     fIsOval = false;
   1558 
   1559     bool needMove = true;
   1560     bool needClose = false;
   1561     while (verbs < verbsEnd) {
   1562         uint8_t v = *(verbs++);
   1563         int n = pts_in_verb(v);
   1564 
   1565         if (needMove) {
   1566             --pts;
   1567             this->moveTo(pts->fX, pts->fY);
   1568             needMove = false;
   1569         }
   1570         pts -= n;
   1571         switch (v) {
   1572             case kMove_Verb:
   1573                 if (needClose) {
   1574                     this->close();
   1575                     needClose = false;
   1576                 }
   1577                 needMove = true;
   1578                 pts += 1;   // so we see the point in "if (needMove)" above
   1579                 break;
   1580             case kLine_Verb:
   1581                 this->lineTo(pts[0]);
   1582                 break;
   1583             case kQuad_Verb:
   1584                 this->quadTo(pts[1], pts[0]);
   1585                 break;
   1586             case kConic_Verb:
   1587                 this->conicTo(pts[1], pts[0], *--conicWeights);
   1588                 break;
   1589             case kCubic_Verb:
   1590                 this->cubicTo(pts[2], pts[1], pts[0]);
   1591                 break;
   1592             case kClose_Verb:
   1593                 needClose = true;
   1594                 break;
   1595             default:
   1596                 SkASSERT(!"unexpected verb");
   1597         }
   1598     }
   1599 }
   1600 
   1601 ///////////////////////////////////////////////////////////////////////////////
   1602 
   1603 void SkPath::offset(SkScalar dx, SkScalar dy, SkPath* dst) const {
   1604     SkMatrix    matrix;
   1605 
   1606     matrix.setTranslate(dx, dy);
   1607     this->transform(matrix, dst);
   1608 }
   1609 
   1610 #include "SkGeometry.h"
   1611 
   1612 static void subdivide_quad_to(SkPath* path, const SkPoint pts[3],
   1613                               int level = 2) {
   1614     if (--level >= 0) {
   1615         SkPoint tmp[5];
   1616 
   1617         SkChopQuadAtHalf(pts, tmp);
   1618         subdivide_quad_to(path, &tmp[0], level);
   1619         subdivide_quad_to(path, &tmp[2], level);
   1620     } else {
   1621         path->quadTo(pts[1], pts[2]);
   1622     }
   1623 }
   1624 
   1625 static void subdivide_cubic_to(SkPath* path, const SkPoint pts[4],
   1626                                int level = 2) {
   1627     if (--level >= 0) {
   1628         SkPoint tmp[7];
   1629 
   1630         SkChopCubicAtHalf(pts, tmp);
   1631         subdivide_cubic_to(path, &tmp[0], level);
   1632         subdivide_cubic_to(path, &tmp[3], level);
   1633     } else {
   1634         path->cubicTo(pts[1], pts[2], pts[3]);
   1635     }
   1636 }
   1637 
   1638 void SkPath::transform(const SkMatrix& matrix, SkPath* dst) const {
   1639     SkDEBUGCODE(this->validate();)
   1640     if (dst == NULL) {
   1641         dst = (SkPath*)this;
   1642     }
   1643 
   1644     if (matrix.hasPerspective()) {
   1645         SkPath  tmp;
   1646         tmp.fFillType = fFillType;
   1647 
   1648         SkPath::Iter    iter(*this, false);
   1649         SkPoint         pts[4];
   1650         SkPath::Verb    verb;
   1651 
   1652         while ((verb = iter.next(pts, false)) != kDone_Verb) {
   1653             switch (verb) {
   1654                 case kMove_Verb:
   1655                     tmp.moveTo(pts[0]);
   1656                     break;
   1657                 case kLine_Verb:
   1658                     tmp.lineTo(pts[1]);
   1659                     break;
   1660                 case kQuad_Verb:
   1661                     subdivide_quad_to(&tmp, pts);
   1662                     break;
   1663                 case kConic_Verb:
   1664                     SkASSERT(!"TODO: compute new weight");
   1665                     tmp.conicTo(pts[1], pts[2], iter.conicWeight());
   1666                     break;
   1667                 case kCubic_Verb:
   1668                     subdivide_cubic_to(&tmp, pts);
   1669                     break;
   1670                 case kClose_Verb:
   1671                     tmp.close();
   1672                     break;
   1673                 default:
   1674                     SkDEBUGFAIL("unknown verb");
   1675                     break;
   1676             }
   1677         }
   1678 
   1679         dst->swap(tmp);
   1680         SkPathRef::Editor ed(&dst->fPathRef);
   1681         matrix.mapPoints(ed.points(), ed.pathRef()->countPoints());
   1682         dst->fDirection = kUnknown_Direction;
   1683     } else {
   1684         /*
   1685          *  If we're not in perspective, we can transform all of the points at
   1686          *  once.
   1687          *
   1688          *  Here we also want to optimize bounds, by noting if the bounds are
   1689          *  already known, and if so, we just transform those as well and mark
   1690          *  them as "known", rather than force the transformed path to have to
   1691          *  recompute them.
   1692          *
   1693          *  Special gotchas if the path is effectively empty (<= 1 point) or
   1694          *  if it is non-finite. In those cases bounds need to stay empty,
   1695          *  regardless of the matrix.
   1696          */
   1697         if (!fBoundsIsDirty && matrix.rectStaysRect() && fPathRef->countPoints() > 1) {
   1698             dst->fBoundsIsDirty = false;
   1699             if (fIsFinite) {
   1700                 matrix.mapRect(&dst->fBounds, fBounds);
   1701                 if (!(dst->fIsFinite = dst->fBounds.isFinite())) {
   1702                     dst->fBounds.setEmpty();
   1703                 }
   1704             } else {
   1705                 dst->fIsFinite = false;
   1706                 dst->fBounds.setEmpty();
   1707             }
   1708         } else {
   1709             GEN_ID_PTR_INC(dst);
   1710             dst->fBoundsIsDirty = true;
   1711         }
   1712 
   1713         SkPathRef::CreateTransformedCopy(&dst->fPathRef, *fPathRef.get(), matrix);
   1714 
   1715         if (this != dst) {
   1716             dst->fFillType = fFillType;
   1717             dst->fSegmentMask = fSegmentMask;
   1718             dst->fConvexity = fConvexity;
   1719         }
   1720 
   1721 #ifdef SK_BUILD_FOR_ANDROID
   1722         if (!matrix.isIdentity()) {
   1723             GEN_ID_PTR_INC(dst);
   1724         }
   1725 #endif
   1726 
   1727         if (kUnknown_Direction == fDirection) {
   1728             dst->fDirection = kUnknown_Direction;
   1729         } else {
   1730             SkScalar det2x2 =
   1731                 SkScalarMul(matrix.get(SkMatrix::kMScaleX), matrix.get(SkMatrix::kMScaleY)) -
   1732                 SkScalarMul(matrix.get(SkMatrix::kMSkewX), matrix.get(SkMatrix::kMSkewY));
   1733             if (det2x2 < 0) {
   1734                 dst->fDirection = SkPath::OppositeDirection(static_cast<Direction>(fDirection));
   1735             } else if (det2x2 > 0) {
   1736                 dst->fDirection = fDirection;
   1737             } else {
   1738                 dst->fDirection = kUnknown_Direction;
   1739             }
   1740         }
   1741 
   1742         // It's an oval only if it stays a rect.
   1743         dst->fIsOval = fIsOval && matrix.rectStaysRect();
   1744 
   1745         SkDEBUGCODE(dst->validate();)
   1746     }
   1747 }
   1748 
   1749 ///////////////////////////////////////////////////////////////////////////////
   1750 ///////////////////////////////////////////////////////////////////////////////
   1751 
   1752 enum SegmentState {
   1753     kEmptyContour_SegmentState,   // The current contour is empty. We may be
   1754                                   // starting processing or we may have just
   1755                                   // closed a contour.
   1756     kAfterMove_SegmentState,      // We have seen a move, but nothing else.
   1757     kAfterPrimitive_SegmentState  // We have seen a primitive but not yet
   1758                                   // closed the path. Also the initial state.
   1759 };
   1760 
   1761 SkPath::Iter::Iter() {
   1762 #ifdef SK_DEBUG
   1763     fPts = NULL;
   1764     fConicWeights = NULL;
   1765     fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0;
   1766     fForceClose = fCloseLine = false;
   1767     fSegmentState = kEmptyContour_SegmentState;
   1768 #endif
   1769     // need to init enough to make next() harmlessly return kDone_Verb
   1770     fVerbs = NULL;
   1771     fVerbStop = NULL;
   1772     fNeedClose = false;
   1773 }
   1774 
   1775 SkPath::Iter::Iter(const SkPath& path, bool forceClose) {
   1776     this->setPath(path, forceClose);
   1777 }
   1778 
   1779 void SkPath::Iter::setPath(const SkPath& path, bool forceClose) {
   1780     fPts = path.fPathRef->points();
   1781     fVerbs = path.fPathRef->verbs();
   1782     fVerbStop = path.fPathRef->verbsMemBegin();
   1783     fConicWeights = path.fPathRef->conicWeights() - 1; // begin one behind
   1784     fLastPt.fX = fLastPt.fY = 0;
   1785     fMoveTo.fX = fMoveTo.fY = 0;
   1786     fForceClose = SkToU8(forceClose);
   1787     fNeedClose = false;
   1788     fSegmentState = kEmptyContour_SegmentState;
   1789 }
   1790 
   1791 bool SkPath::Iter::isClosedContour() const {
   1792     if (fVerbs == NULL || fVerbs == fVerbStop) {
   1793         return false;
   1794     }
   1795     if (fForceClose) {
   1796         return true;
   1797     }
   1798 
   1799     const uint8_t* verbs = fVerbs;
   1800     const uint8_t* stop = fVerbStop;
   1801 
   1802     if (kMove_Verb == *(verbs - 1)) {
   1803         verbs -= 1; // skip the initial moveto
   1804     }
   1805 
   1806     while (verbs > stop) {
   1807         // verbs points one beyond the current verb, decrement first.
   1808         unsigned v = *(--verbs);
   1809         if (kMove_Verb == v) {
   1810             break;
   1811         }
   1812         if (kClose_Verb == v) {
   1813             return true;
   1814         }
   1815     }
   1816     return false;
   1817 }
   1818 
   1819 SkPath::Verb SkPath::Iter::autoClose(SkPoint pts[2]) {
   1820     SkASSERT(pts);
   1821     if (fLastPt != fMoveTo) {
   1822         // A special case: if both points are NaN, SkPoint::operation== returns
   1823         // false, but the iterator expects that they are treated as the same.
   1824         // (consider SkPoint is a 2-dimension float point).
   1825         if (SkScalarIsNaN(fLastPt.fX) || SkScalarIsNaN(fLastPt.fY) ||
   1826             SkScalarIsNaN(fMoveTo.fX) || SkScalarIsNaN(fMoveTo.fY)) {
   1827             return kClose_Verb;
   1828         }
   1829 
   1830         pts[0] = fLastPt;
   1831         pts[1] = fMoveTo;
   1832         fLastPt = fMoveTo;
   1833         fCloseLine = true;
   1834         return kLine_Verb;
   1835     } else {
   1836         pts[0] = fMoveTo;
   1837         return kClose_Verb;
   1838     }
   1839 }
   1840 
   1841 const SkPoint& SkPath::Iter::cons_moveTo() {
   1842     if (fSegmentState == kAfterMove_SegmentState) {
   1843         // Set the first return pt to the move pt
   1844         fSegmentState = kAfterPrimitive_SegmentState;
   1845         return fMoveTo;
   1846     } else {
   1847         SkASSERT(fSegmentState == kAfterPrimitive_SegmentState);
   1848          // Set the first return pt to the last pt of the previous primitive.
   1849         return fPts[-1];
   1850     }
   1851 }
   1852 
   1853 void SkPath::Iter::consumeDegenerateSegments() {
   1854     // We need to step over anything that will not move the current draw point
   1855     // forward before the next move is seen
   1856     const uint8_t* lastMoveVerb = 0;
   1857     const SkPoint* lastMovePt = 0;
   1858     SkPoint lastPt = fLastPt;
   1859     while (fVerbs != fVerbStop) {
   1860         unsigned verb = *(fVerbs - 1); // fVerbs is one beyond the current verb
   1861         switch (verb) {
   1862             case kMove_Verb:
   1863                 // Keep a record of this most recent move
   1864                 lastMoveVerb = fVerbs;
   1865                 lastMovePt = fPts;
   1866                 lastPt = fPts[0];
   1867                 fVerbs--;
   1868                 fPts++;
   1869                 break;
   1870 
   1871             case kClose_Verb:
   1872                 // A close when we are in a segment is always valid except when it
   1873                 // follows a move which follows a segment.
   1874                 if (fSegmentState == kAfterPrimitive_SegmentState && !lastMoveVerb) {
   1875                     return;
   1876                 }
   1877                 // A close at any other time must be ignored
   1878                 fVerbs--;
   1879                 break;
   1880 
   1881             case kLine_Verb:
   1882                 if (!IsLineDegenerate(lastPt, fPts[0])) {
   1883                     if (lastMoveVerb) {
   1884                         fVerbs = lastMoveVerb;
   1885                         fPts = lastMovePt;
   1886                         return;
   1887                     }
   1888                     return;
   1889                 }
   1890                 // Ignore this line and continue
   1891                 fVerbs--;
   1892                 fPts++;
   1893                 break;
   1894 
   1895             case kConic_Verb:
   1896             case kQuad_Verb:
   1897                 if (!IsQuadDegenerate(lastPt, fPts[0], fPts[1])) {
   1898                     if (lastMoveVerb) {
   1899                         fVerbs = lastMoveVerb;
   1900                         fPts = lastMovePt;
   1901                         return;
   1902                     }
   1903                     return;
   1904                 }
   1905                 // Ignore this line and continue
   1906                 fVerbs--;
   1907                 fPts += 2;
   1908                 fConicWeights += (kConic_Verb == verb);
   1909                 break;
   1910 
   1911             case kCubic_Verb:
   1912                 if (!IsCubicDegenerate(lastPt, fPts[0], fPts[1], fPts[2])) {
   1913                     if (lastMoveVerb) {
   1914                         fVerbs = lastMoveVerb;
   1915                         fPts = lastMovePt;
   1916                         return;
   1917                     }
   1918                     return;
   1919                 }
   1920                 // Ignore this line and continue
   1921                 fVerbs--;
   1922                 fPts += 3;
   1923                 break;
   1924 
   1925             default:
   1926                 SkDEBUGFAIL("Should never see kDone_Verb");
   1927         }
   1928     }
   1929 }
   1930 
   1931 SkPath::Verb SkPath::Iter::doNext(SkPoint ptsParam[4]) {
   1932     SkASSERT(ptsParam);
   1933 
   1934     if (fVerbs == fVerbStop) {
   1935         // Close the curve if requested and if there is some curve to close
   1936         if (fNeedClose && fSegmentState == kAfterPrimitive_SegmentState) {
   1937             if (kLine_Verb == this->autoClose(ptsParam)) {
   1938                 return kLine_Verb;
   1939             }
   1940             fNeedClose = false;
   1941             return kClose_Verb;
   1942         }
   1943         return kDone_Verb;
   1944     }
   1945 
   1946     // fVerbs is one beyond the current verb, decrement first
   1947     unsigned verb = *(--fVerbs);
   1948     const SkPoint* SK_RESTRICT srcPts = fPts;
   1949     SkPoint* SK_RESTRICT       pts = ptsParam;
   1950 
   1951     switch (verb) {
   1952         case kMove_Verb:
   1953             if (fNeedClose) {
   1954                 fVerbs++; // move back one verb
   1955                 verb = this->autoClose(pts);
   1956                 if (verb == kClose_Verb) {
   1957                     fNeedClose = false;
   1958                 }
   1959                 return (Verb)verb;
   1960             }
   1961             if (fVerbs == fVerbStop) {    // might be a trailing moveto
   1962                 return kDone_Verb;
   1963             }
   1964             fMoveTo = *srcPts;
   1965             pts[0] = *srcPts;
   1966             srcPts += 1;
   1967             fSegmentState = kAfterMove_SegmentState;
   1968             fLastPt = fMoveTo;
   1969             fNeedClose = fForceClose;
   1970             break;
   1971         case kLine_Verb:
   1972             pts[0] = this->cons_moveTo();
   1973             pts[1] = srcPts[0];
   1974             fLastPt = srcPts[0];
   1975             fCloseLine = false;
   1976             srcPts += 1;
   1977             break;
   1978         case kConic_Verb:
   1979             fConicWeights += 1;
   1980             // fall-through
   1981         case kQuad_Verb:
   1982             pts[0] = this->cons_moveTo();
   1983             memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint));
   1984             fLastPt = srcPts[1];
   1985             srcPts += 2;
   1986             break;
   1987         case kCubic_Verb:
   1988             pts[0] = this->cons_moveTo();
   1989             memcpy(&pts[1], srcPts, 3 * sizeof(SkPoint));
   1990             fLastPt = srcPts[2];
   1991             srcPts += 3;
   1992             break;
   1993         case kClose_Verb:
   1994             verb = this->autoClose(pts);
   1995             if (verb == kLine_Verb) {
   1996                 fVerbs++; // move back one verb
   1997             } else {
   1998                 fNeedClose = false;
   1999                 fSegmentState = kEmptyContour_SegmentState;
   2000             }
   2001             fLastPt = fMoveTo;
   2002             break;
   2003     }
   2004     fPts = srcPts;
   2005     return (Verb)verb;
   2006 }
   2007 
   2008 ///////////////////////////////////////////////////////////////////////////////
   2009 
   2010 SkPath::RawIter::RawIter() {
   2011 #ifdef SK_DEBUG
   2012     fPts = NULL;
   2013     fConicWeights = NULL;
   2014     fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0;
   2015 #endif
   2016     // need to init enough to make next() harmlessly return kDone_Verb
   2017     fVerbs = NULL;
   2018     fVerbStop = NULL;
   2019 }
   2020 
   2021 SkPath::RawIter::RawIter(const SkPath& path) {
   2022     this->setPath(path);
   2023 }
   2024 
   2025 void SkPath::RawIter::setPath(const SkPath& path) {
   2026     fPts = path.fPathRef->points();
   2027     fVerbs = path.fPathRef->verbs();
   2028     fVerbStop = path.fPathRef->verbsMemBegin();
   2029     fConicWeights = path.fPathRef->conicWeights() - 1; // begin one behind
   2030     fMoveTo.fX = fMoveTo.fY = 0;
   2031     fLastPt.fX = fLastPt.fY = 0;
   2032 }
   2033 
   2034 SkPath::Verb SkPath::RawIter::next(SkPoint pts[4]) {
   2035     SkASSERT(NULL != pts);
   2036     if (fVerbs == fVerbStop) {
   2037         return kDone_Verb;
   2038     }
   2039 
   2040     // fVerbs points one beyond next verb so decrement first.
   2041     unsigned verb = *(--fVerbs);
   2042     const SkPoint* srcPts = fPts;
   2043 
   2044     switch (verb) {
   2045         case kMove_Verb:
   2046             pts[0] = *srcPts;
   2047             fMoveTo = srcPts[0];
   2048             fLastPt = fMoveTo;
   2049             srcPts += 1;
   2050             break;
   2051         case kLine_Verb:
   2052             pts[0] = fLastPt;
   2053             pts[1] = srcPts[0];
   2054             fLastPt = srcPts[0];
   2055             srcPts += 1;
   2056             break;
   2057         case kConic_Verb:
   2058             fConicWeights += 1;
   2059             // fall-through
   2060         case kQuad_Verb:
   2061             pts[0] = fLastPt;
   2062             memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint));
   2063             fLastPt = srcPts[1];
   2064             srcPts += 2;
   2065             break;
   2066         case kCubic_Verb:
   2067             pts[0] = fLastPt;
   2068             memcpy(&pts[1], srcPts, 3 * sizeof(SkPoint));
   2069             fLastPt = srcPts[2];
   2070             srcPts += 3;
   2071             break;
   2072         case kClose_Verb:
   2073             fLastPt = fMoveTo;
   2074             pts[0] = fMoveTo;
   2075             break;
   2076     }
   2077     fPts = srcPts;
   2078     return (Verb)verb;
   2079 }
   2080 
   2081 ///////////////////////////////////////////////////////////////////////////////
   2082 
   2083 /*
   2084     Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]]
   2085 */
   2086 
   2087 uint32_t SkPath::writeToMemory(void* storage) const {
   2088     SkDEBUGCODE(this->validate();)
   2089 
   2090     if (NULL == storage) {
   2091         const int byteCount = sizeof(int32_t)
   2092                       + fPathRef->writeSize()
   2093                       + sizeof(SkRect);
   2094         return SkAlign4(byteCount);
   2095     }
   2096 
   2097     SkWBuffer   buffer(storage);
   2098 
   2099     // Call getBounds() to ensure (as a side-effect) that fBounds
   2100     // and fIsFinite are computed.
   2101     const SkRect& bounds = this->getBounds();
   2102     SkASSERT(!fBoundsIsDirty);
   2103 
   2104     int32_t packed = ((fIsFinite & 1) << kIsFinite_SerializationShift) |
   2105                      ((fIsOval & 1) << kIsOval_SerializationShift) |
   2106                      (fConvexity << kConvexity_SerializationShift) |
   2107                      (fFillType << kFillType_SerializationShift) |
   2108                      (fSegmentMask << kSegmentMask_SerializationShift) |
   2109                      (fDirection << kDirection_SerializationShift);
   2110 
   2111     buffer.write32(packed);
   2112 
   2113     fPathRef->writeToBuffer(&buffer);
   2114 
   2115     buffer.write(&bounds, sizeof(bounds));
   2116 
   2117     buffer.padToAlign4();
   2118     return SkToU32(buffer.pos());
   2119 }
   2120 
   2121 uint32_t SkPath::readFromMemory(const void* storage) {
   2122     SkRBuffer   buffer(storage);
   2123 
   2124     uint32_t packed = buffer.readS32();
   2125     fIsFinite = (packed >> kIsFinite_SerializationShift) & 1;
   2126     fIsOval = (packed >> kIsOval_SerializationShift) & 1;
   2127     fConvexity = (packed >> kConvexity_SerializationShift) & 0xFF;
   2128     fFillType = (packed >> kFillType_SerializationShift) & 0xFF;
   2129     fSegmentMask = (packed >> kSegmentMask_SerializationShift) & 0xF;
   2130     fDirection = (packed >> kDirection_SerializationShift) & 0x3;
   2131 
   2132     fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer));
   2133 
   2134     buffer.read(&fBounds, sizeof(fBounds));
   2135     fBoundsIsDirty = false;
   2136 
   2137     buffer.skipToAlign4();
   2138 
   2139     GEN_ID_INC;
   2140 
   2141     SkDEBUGCODE(this->validate();)
   2142     return SkToU32(buffer.pos());
   2143 }
   2144 
   2145 ///////////////////////////////////////////////////////////////////////////////
   2146 
   2147 #include "SkString.h"
   2148 
   2149 static void append_scalar(SkString* str, SkScalar value) {
   2150     SkString tmp;
   2151     tmp.printf("%g", value);
   2152     if (tmp.contains('.')) {
   2153         tmp.appendUnichar('f');
   2154     }
   2155     str->append(tmp);
   2156 }
   2157 
   2158 static void append_params(SkString* str, const char label[], const SkPoint pts[],
   2159                           int count, SkScalar conicWeight = -1) {
   2160     str->append(label);
   2161     str->append("(");
   2162 
   2163     const SkScalar* values = &pts[0].fX;
   2164     count *= 2;
   2165 
   2166     for (int i = 0; i < count; ++i) {
   2167         append_scalar(str, values[i]);
   2168         if (i < count - 1) {
   2169             str->append(", ");
   2170         }
   2171     }
   2172     if (conicWeight >= 0) {
   2173         str->append(", ");
   2174         append_scalar(str, conicWeight);
   2175     }
   2176     str->append(");\n");
   2177 }
   2178 
   2179 void SkPath::dump(bool forceClose, const char title[]) const {
   2180     Iter    iter(*this, forceClose);
   2181     SkPoint pts[4];
   2182     Verb    verb;
   2183 
   2184     SkDebugf("path: forceClose=%s %s\n", forceClose ? "true" : "false",
   2185              title ? title : "");
   2186 
   2187     SkString builder;
   2188 
   2189     while ((verb = iter.next(pts, false)) != kDone_Verb) {
   2190         switch (verb) {
   2191             case kMove_Verb:
   2192                 append_params(&builder, "path.moveTo", &pts[0], 1);
   2193                 break;
   2194             case kLine_Verb:
   2195                 append_params(&builder, "path.lineTo", &pts[1], 1);
   2196                 break;
   2197             case kQuad_Verb:
   2198                 append_params(&builder, "path.quadTo", &pts[1], 2);
   2199                 break;
   2200             case kConic_Verb:
   2201                 append_params(&builder, "path.conicTo", &pts[1], 2, iter.conicWeight());
   2202                 break;
   2203             case kCubic_Verb:
   2204                 append_params(&builder, "path.cubicTo", &pts[1], 3);
   2205                 break;
   2206             case kClose_Verb:
   2207                 builder.append("path.close();\n");
   2208                 break;
   2209             default:
   2210                 SkDebugf("  path: UNKNOWN VERB %d, aborting dump...\n", verb);
   2211                 verb = kDone_Verb;  // stop the loop
   2212                 break;
   2213         }
   2214     }
   2215     SkDebugf("%s\n", builder.c_str());
   2216 }
   2217 
   2218 void SkPath::dump() const {
   2219     this->dump(false);
   2220 }
   2221 
   2222 #ifdef SK_DEBUG
   2223 void SkPath::validate() const {
   2224     SkASSERT(this != NULL);
   2225     SkASSERT((fFillType & ~3) == 0);
   2226 
   2227 #ifdef SK_DEBUG_PATH
   2228     if (!fBoundsIsDirty) {
   2229         SkRect bounds;
   2230 
   2231         bool isFinite = compute_pt_bounds(&bounds, *fPathRef.get());
   2232         SkASSERT(SkToBool(fIsFinite) == isFinite);
   2233 
   2234         if (fPathRef->countPoints() <= 1) {
   2235             // if we're empty, fBounds may be empty but translated, so we can't
   2236             // necessarily compare to bounds directly
   2237             // try path.addOval(2, 2, 2, 2) which is empty, but the bounds will
   2238             // be [2, 2, 2, 2]
   2239             SkASSERT(bounds.isEmpty());
   2240             SkASSERT(fBounds.isEmpty());
   2241         } else {
   2242             if (bounds.isEmpty()) {
   2243                 SkASSERT(fBounds.isEmpty());
   2244             } else {
   2245                 if (!fBounds.isEmpty()) {
   2246                     SkASSERT(fBounds.contains(bounds));
   2247                 }
   2248             }
   2249         }
   2250     }
   2251 
   2252     uint32_t mask = 0;
   2253     const uint8_t* verbs = const_cast<const SkPathRef*>(fPathRef.get())->verbs();
   2254     for (int i = 0; i < fPathRef->countVerbs(); i++) {
   2255         switch (verbs[~i]) {
   2256             case kLine_Verb:
   2257                 mask |= kLine_SegmentMask;
   2258                 break;
   2259             case kQuad_Verb:
   2260                 mask |= kQuad_SegmentMask;
   2261                 break;
   2262             case kConic_Verb:
   2263                 mask |= kConic_SegmentMask;
   2264                 break;
   2265             case kCubic_Verb:
   2266                 mask |= kCubic_SegmentMask;
   2267             case kMove_Verb:  // these verbs aren't included in the segment mask.
   2268             case kClose_Verb:
   2269                 break;
   2270             case kDone_Verb:
   2271                 SkDEBUGFAIL("Done verb shouldn't be recorded.");
   2272                 break;
   2273             default:
   2274                 SkDEBUGFAIL("Unknown Verb");
   2275                 break;
   2276         }
   2277     }
   2278     SkASSERT(mask == fSegmentMask);
   2279 #endif // SK_DEBUG_PATH
   2280 }
   2281 #endif // SK_DEBUG
   2282 
   2283 ///////////////////////////////////////////////////////////////////////////////
   2284 
   2285 static int sign(SkScalar x) { return x < 0; }
   2286 #define kValueNeverReturnedBySign   2
   2287 
   2288 static int CrossProductSign(const SkVector& a, const SkVector& b) {
   2289     return SkScalarSignAsInt(SkPoint::CrossProduct(a, b));
   2290 }
   2291 
   2292 // only valid for a single contour
   2293 struct Convexicator {
   2294     Convexicator()
   2295     : fPtCount(0)
   2296     , fConvexity(SkPath::kConvex_Convexity)
   2297     , fDirection(SkPath::kUnknown_Direction) {
   2298         fSign = 0;
   2299         // warnings
   2300         fCurrPt.set(0, 0);
   2301         fVec0.set(0, 0);
   2302         fVec1.set(0, 0);
   2303         fFirstVec.set(0, 0);
   2304 
   2305         fDx = fDy = 0;
   2306         fSx = fSy = kValueNeverReturnedBySign;
   2307     }
   2308 
   2309     SkPath::Convexity getConvexity() const { return fConvexity; }
   2310 
   2311     /** The direction returned is only valid if the path is determined convex */
   2312     SkPath::Direction getDirection() const { return fDirection; }
   2313 
   2314     void addPt(const SkPoint& pt) {
   2315         if (SkPath::kConcave_Convexity == fConvexity) {
   2316             return;
   2317         }
   2318 
   2319         if (0 == fPtCount) {
   2320             fCurrPt = pt;
   2321             ++fPtCount;
   2322         } else {
   2323             SkVector vec = pt - fCurrPt;
   2324             if (vec.fX || vec.fY) {
   2325                 fCurrPt = pt;
   2326                 if (++fPtCount == 2) {
   2327                     fFirstVec = fVec1 = vec;
   2328                 } else {
   2329                     SkASSERT(fPtCount > 2);
   2330                     this->addVec(vec);
   2331                 }
   2332 
   2333                 int sx = sign(vec.fX);
   2334                 int sy = sign(vec.fY);
   2335                 fDx += (sx != fSx);
   2336                 fDy += (sy != fSy);
   2337                 fSx = sx;
   2338                 fSy = sy;
   2339 
   2340                 if (fDx > 3 || fDy > 3) {
   2341                     fConvexity = SkPath::kConcave_Convexity;
   2342                 }
   2343             }
   2344         }
   2345     }
   2346 
   2347     void close() {
   2348         if (fPtCount > 2) {
   2349             this->addVec(fFirstVec);
   2350         }
   2351     }
   2352 
   2353 private:
   2354     void addVec(const SkVector& vec) {
   2355         SkASSERT(vec.fX || vec.fY);
   2356         fVec0 = fVec1;
   2357         fVec1 = vec;
   2358         int sign = CrossProductSign(fVec0, fVec1);
   2359         if (0 == fSign) {
   2360             fSign = sign;
   2361             if (1 == sign) {
   2362                 fDirection = SkPath::kCW_Direction;
   2363             } else if (-1 == sign) {
   2364                 fDirection = SkPath::kCCW_Direction;
   2365             }
   2366         } else if (sign) {
   2367             if (fSign != sign) {
   2368                 fConvexity = SkPath::kConcave_Convexity;
   2369                 fDirection = SkPath::kUnknown_Direction;
   2370             }
   2371         }
   2372     }
   2373 
   2374     SkPoint             fCurrPt;
   2375     SkVector            fVec0, fVec1, fFirstVec;
   2376     int                 fPtCount;   // non-degenerate points
   2377     int                 fSign;
   2378     SkPath::Convexity   fConvexity;
   2379     SkPath::Direction   fDirection;
   2380     int                 fDx, fDy, fSx, fSy;
   2381 };
   2382 
   2383 SkPath::Convexity SkPath::internalGetConvexity() const {
   2384     SkASSERT(kUnknown_Convexity == fConvexity);
   2385     SkPoint         pts[4];
   2386     SkPath::Verb    verb;
   2387     SkPath::Iter    iter(*this, true);
   2388 
   2389     int             contourCount = 0;
   2390     int             count;
   2391     Convexicator    state;
   2392 
   2393     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
   2394         switch (verb) {
   2395             case kMove_Verb:
   2396                 if (++contourCount > 1) {
   2397                     fConvexity = kConcave_Convexity;
   2398                     return kConcave_Convexity;
   2399                 }
   2400                 pts[1] = pts[0];
   2401                 count = 1;
   2402                 break;
   2403             case kLine_Verb: count = 1; break;
   2404             case kQuad_Verb: count = 2; break;
   2405             case kConic_Verb: count = 2; break;
   2406             case kCubic_Verb: count = 3; break;
   2407             case kClose_Verb:
   2408                 state.close();
   2409                 count = 0;
   2410                 break;
   2411             default:
   2412                 SkDEBUGFAIL("bad verb");
   2413                 fConvexity = kConcave_Convexity;
   2414                 return kConcave_Convexity;
   2415         }
   2416 
   2417         for (int i = 1; i <= count; i++) {
   2418             state.addPt(pts[i]);
   2419         }
   2420         // early exit
   2421         if (kConcave_Convexity == state.getConvexity()) {
   2422             fConvexity = kConcave_Convexity;
   2423             return kConcave_Convexity;
   2424         }
   2425     }
   2426     fConvexity = state.getConvexity();
   2427     if (kConvex_Convexity == fConvexity && kUnknown_Direction == fDirection) {
   2428         fDirection = state.getDirection();
   2429     }
   2430     return static_cast<Convexity>(fConvexity);
   2431 }
   2432 
   2433 ///////////////////////////////////////////////////////////////////////////////
   2434 
   2435 class ContourIter {
   2436 public:
   2437     ContourIter(const SkPathRef& pathRef);
   2438 
   2439     bool done() const { return fDone; }
   2440     // if !done() then these may be called
   2441     int count() const { return fCurrPtCount; }
   2442     const SkPoint* pts() const { return fCurrPt; }
   2443     void next();
   2444 
   2445 private:
   2446     int fCurrPtCount;
   2447     const SkPoint* fCurrPt;
   2448     const uint8_t* fCurrVerb;
   2449     const uint8_t* fStopVerbs;
   2450     const SkScalar* fCurrConicWeight;
   2451     bool fDone;
   2452     SkDEBUGCODE(int fContourCounter;)
   2453 };
   2454 
   2455 ContourIter::ContourIter(const SkPathRef& pathRef) {
   2456     fStopVerbs = pathRef.verbsMemBegin();
   2457     fDone = false;
   2458     fCurrPt = pathRef.points();
   2459     fCurrVerb = pathRef.verbs();
   2460     fCurrConicWeight = pathRef.conicWeights();
   2461     fCurrPtCount = 0;
   2462     SkDEBUGCODE(fContourCounter = 0;)
   2463     this->next();
   2464 }
   2465 
   2466 void ContourIter::next() {
   2467     if (fCurrVerb <= fStopVerbs) {
   2468         fDone = true;
   2469     }
   2470     if (fDone) {
   2471         return;
   2472     }
   2473 
   2474     // skip pts of prev contour
   2475     fCurrPt += fCurrPtCount;
   2476 
   2477     SkASSERT(SkPath::kMove_Verb == fCurrVerb[~0]);
   2478     int ptCount = 1;    // moveTo
   2479     const uint8_t* verbs = fCurrVerb;
   2480 
   2481     for (--verbs; verbs > fStopVerbs; --verbs) {
   2482         switch (verbs[~0]) {
   2483             case SkPath::kMove_Verb:
   2484                 goto CONTOUR_END;
   2485             case SkPath::kLine_Verb:
   2486                 ptCount += 1;
   2487                 break;
   2488             case SkPath::kConic_Verb:
   2489                 fCurrConicWeight += 1;
   2490                 // fall-through
   2491             case SkPath::kQuad_Verb:
   2492                 ptCount += 2;
   2493                 break;
   2494             case SkPath::kCubic_Verb:
   2495                 ptCount += 3;
   2496                 break;
   2497             case SkPath::kClose_Verb:
   2498                 break;
   2499             default:
   2500                 SkASSERT(!"unexpected verb");
   2501                 break;
   2502         }
   2503     }
   2504 CONTOUR_END:
   2505     fCurrPtCount = ptCount;
   2506     fCurrVerb = verbs;
   2507     SkDEBUGCODE(++fContourCounter;)
   2508 }
   2509 
   2510 // returns cross product of (p1 - p0) and (p2 - p0)
   2511 static SkScalar cross_prod(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2) {
   2512     SkScalar cross = SkPoint::CrossProduct(p1 - p0, p2 - p0);
   2513     // We may get 0 when the above subtracts underflow. We expect this to be
   2514     // very rare and lazily promote to double.
   2515     if (0 == cross) {
   2516         double p0x = SkScalarToDouble(p0.fX);
   2517         double p0y = SkScalarToDouble(p0.fY);
   2518 
   2519         double p1x = SkScalarToDouble(p1.fX);
   2520         double p1y = SkScalarToDouble(p1.fY);
   2521 
   2522         double p2x = SkScalarToDouble(p2.fX);
   2523         double p2y = SkScalarToDouble(p2.fY);
   2524 
   2525         cross = SkDoubleToScalar((p1x - p0x) * (p2y - p0y) -
   2526                                  (p1y - p0y) * (p2x - p0x));
   2527 
   2528     }
   2529     return cross;
   2530 }
   2531 
   2532 // Returns the first pt with the maximum Y coordinate
   2533 static int find_max_y(const SkPoint pts[], int count) {
   2534     SkASSERT(count > 0);
   2535     SkScalar max = pts[0].fY;
   2536     int firstIndex = 0;
   2537     for (int i = 1; i < count; ++i) {
   2538         SkScalar y = pts[i].fY;
   2539         if (y > max) {
   2540             max = y;
   2541             firstIndex = i;
   2542         }
   2543     }
   2544     return firstIndex;
   2545 }
   2546 
   2547 static int find_diff_pt(const SkPoint pts[], int index, int n, int inc) {
   2548     int i = index;
   2549     for (;;) {
   2550         i = (i + inc) % n;
   2551         if (i == index) {   // we wrapped around, so abort
   2552             break;
   2553         }
   2554         if (pts[index] != pts[i]) { // found a different point, success!
   2555             break;
   2556         }
   2557     }
   2558     return i;
   2559 }
   2560 
   2561 /**
   2562  *  Starting at index, and moving forward (incrementing), find the xmin and
   2563  *  xmax of the contiguous points that have the same Y.
   2564  */
   2565 static int find_min_max_x_at_y(const SkPoint pts[], int index, int n,
   2566                                int* maxIndexPtr) {
   2567     const SkScalar y = pts[index].fY;
   2568     SkScalar min = pts[index].fX;
   2569     SkScalar max = min;
   2570     int minIndex = index;
   2571     int maxIndex = index;
   2572     for (int i = index + 1; i < n; ++i) {
   2573         if (pts[i].fY != y) {
   2574             break;
   2575         }
   2576         SkScalar x = pts[i].fX;
   2577         if (x < min) {
   2578             min = x;
   2579             minIndex = i;
   2580         } else if (x > max) {
   2581             max = x;
   2582             maxIndex = i;
   2583         }
   2584     }
   2585     *maxIndexPtr = maxIndex;
   2586     return minIndex;
   2587 }
   2588 
   2589 static void crossToDir(SkScalar cross, SkPath::Direction* dir) {
   2590     if (dir) {
   2591         *dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
   2592     }
   2593 }
   2594 
   2595 #if 0
   2596 #include "SkString.h"
   2597 #include "../utils/SkParsePath.h"
   2598 static void dumpPath(const SkPath& path) {
   2599     SkString str;
   2600     SkParsePath::ToSVGString(path, &str);
   2601     SkDebugf("%s\n", str.c_str());
   2602 }
   2603 #endif
   2604 
   2605 namespace {
   2606 // for use with convex_dir_test
   2607 double mul(double a, double b) { return a * b; }
   2608 SkScalar mul(SkScalar a, SkScalar b) { return SkScalarMul(a, b); }
   2609 double toDouble(SkScalar a) { return SkScalarToDouble(a); }
   2610 SkScalar toScalar(SkScalar a) { return a; }
   2611 
   2612 // determines the winding direction of a convex polygon with the precision
   2613 // of T. CAST_SCALAR casts an SkScalar to T.
   2614 template <typename T, T (CAST_SCALAR)(SkScalar)>
   2615 bool convex_dir_test(int n, const SkPoint pts[], SkPath::Direction* dir) {
   2616     // we find the first three points that form a non-degenerate
   2617     // triangle. If there are no such points then the path is
   2618     // degenerate. The first is always point 0. Now we find the second
   2619     // point.
   2620     int i = 0;
   2621     enum { kX = 0, kY = 1 };
   2622     T v0[2];
   2623     while (1) {
   2624         v0[kX] = CAST_SCALAR(pts[i].fX) - CAST_SCALAR(pts[0].fX);
   2625         v0[kY] = CAST_SCALAR(pts[i].fY) - CAST_SCALAR(pts[0].fY);
   2626         if (v0[kX] || v0[kY]) {
   2627             break;
   2628         }
   2629         if (++i == n - 1) {
   2630             return false;
   2631         }
   2632     }
   2633     // now find a third point that is not colinear with the first two
   2634     // points and check the orientation of the triangle (which will be
   2635     // the same as the orientation of the path).
   2636     for (++i; i < n; ++i) {
   2637         T v1[2];
   2638         v1[kX] = CAST_SCALAR(pts[i].fX) - CAST_SCALAR(pts[0].fX);
   2639         v1[kY] = CAST_SCALAR(pts[i].fY) - CAST_SCALAR(pts[0].fY);
   2640         T cross = mul(v0[kX], v1[kY]) - mul(v0[kY], v1[kX]);
   2641         if (0 != cross) {
   2642             *dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
   2643             return true;
   2644         }
   2645     }
   2646     return false;
   2647 }
   2648 }
   2649 
   2650 /*
   2651  *  We loop through all contours, and keep the computed cross-product of the
   2652  *  contour that contained the global y-max. If we just look at the first
   2653  *  contour, we may find one that is wound the opposite way (correctly) since
   2654  *  it is the interior of a hole (e.g. 'o'). Thus we must find the contour
   2655  *  that is outer most (or at least has the global y-max) before we can consider
   2656  *  its cross product.
   2657  */
   2658 bool SkPath::cheapComputeDirection(Direction* dir) const {
   2659 //    dumpPath(*this);
   2660     // don't want to pay the cost for computing this if it
   2661     // is unknown, so we don't call isConvex()
   2662 
   2663     if (kUnknown_Direction != fDirection) {
   2664         *dir = static_cast<Direction>(fDirection);
   2665         return true;
   2666     }
   2667     const Convexity conv = this->getConvexityOrUnknown();
   2668 
   2669     ContourIter iter(*fPathRef.get());
   2670 
   2671     // initialize with our logical y-min
   2672     SkScalar ymax = this->getBounds().fTop;
   2673     SkScalar ymaxCross = 0;
   2674 
   2675     for (; !iter.done(); iter.next()) {
   2676         int n = iter.count();
   2677         if (n < 3) {
   2678             continue;
   2679         }
   2680 
   2681         const SkPoint* pts = iter.pts();
   2682         SkScalar cross = 0;
   2683         if (kConvex_Convexity == conv) {
   2684             // We try first at scalar precision, and then again at double
   2685             // precision. This is because the vectors computed between distant
   2686             // points may lose too much precision.
   2687             if (convex_dir_test<SkScalar, toScalar>(n, pts, dir)) {
   2688                 fDirection = *dir;
   2689                 return true;
   2690             }
   2691             if (convex_dir_test<double, toDouble>(n, pts, dir)) {
   2692                 fDirection = *dir;
   2693                 return true;
   2694             } else {
   2695                 return false;
   2696             }
   2697         } else {
   2698             int index = find_max_y(pts, n);
   2699             if (pts[index].fY < ymax) {
   2700                 continue;
   2701             }
   2702 
   2703             // If there is more than 1 distinct point at the y-max, we take the
   2704             // x-min and x-max of them and just subtract to compute the dir.
   2705             if (pts[(index + 1) % n].fY == pts[index].fY) {
   2706                 int maxIndex;
   2707                 int minIndex = find_min_max_x_at_y(pts, index, n, &maxIndex);
   2708                 if (minIndex == maxIndex) {
   2709                     goto TRY_CROSSPROD;
   2710                 }
   2711                 SkASSERT(pts[minIndex].fY == pts[index].fY);
   2712                 SkASSERT(pts[maxIndex].fY == pts[index].fY);
   2713                 SkASSERT(pts[minIndex].fX <= pts[maxIndex].fX);
   2714                 // we just subtract the indices, and let that auto-convert to
   2715                 // SkScalar, since we just want - or + to signal the direction.
   2716                 cross = minIndex - maxIndex;
   2717             } else {
   2718                 TRY_CROSSPROD:
   2719                 // Find a next and prev index to use for the cross-product test,
   2720                 // but we try to find pts that form non-zero vectors from pts[index]
   2721                 //
   2722                 // Its possible that we can't find two non-degenerate vectors, so
   2723                 // we have to guard our search (e.g. all the pts could be in the
   2724                 // same place).
   2725 
   2726                 // we pass n - 1 instead of -1 so we don't foul up % operator by
   2727                 // passing it a negative LH argument.
   2728                 int prev = find_diff_pt(pts, index, n, n - 1);
   2729                 if (prev == index) {
   2730                     // completely degenerate, skip to next contour
   2731                     continue;
   2732                 }
   2733                 int next = find_diff_pt(pts, index, n, 1);
   2734                 SkASSERT(next != index);
   2735                 cross = cross_prod(pts[prev], pts[index], pts[next]);
   2736                 // if we get a zero and the points are horizontal, then we look at the spread in
   2737                 // x-direction. We really should continue to walk away from the degeneracy until
   2738                 // there is a divergence.
   2739                 if (0 == cross && pts[prev].fY == pts[index].fY && pts[next].fY == pts[index].fY) {
   2740                     // construct the subtract so we get the correct Direction below
   2741                     cross = pts[index].fX - pts[next].fX;
   2742                 }
   2743             }
   2744 
   2745             if (cross) {
   2746                 // record our best guess so far
   2747                 ymax = pts[index].fY;
   2748                 ymaxCross = cross;
   2749             }
   2750         }
   2751     }
   2752     if (ymaxCross) {
   2753         crossToDir(ymaxCross, dir);
   2754         fDirection = *dir;
   2755         return true;
   2756     } else {
   2757         return false;
   2758     }
   2759 }
   2760 
   2761 ///////////////////////////////////////////////////////////////////////////////
   2762 
   2763 static SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C,
   2764                                  SkScalar D, SkScalar t) {
   2765     return SkScalarMulAdd(SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C), t, D);
   2766 }
   2767 
   2768 static SkScalar eval_cubic_pts(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3,
   2769                                SkScalar t) {
   2770     SkScalar A = c3 + 3*(c1 - c2) - c0;
   2771     SkScalar B = 3*(c2 - c1 - c1 + c0);
   2772     SkScalar C = 3*(c1 - c0);
   2773     SkScalar D = c0;
   2774     return eval_cubic_coeff(A, B, C, D, t);
   2775 }
   2776 
   2777 /*  Given 4 cubic points (either Xs or Ys), and a target X or Y, compute the
   2778  t value such that cubic(t) = target
   2779  */
   2780 static bool chopMonoCubicAt(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar c3,
   2781                             SkScalar target, SkScalar* t) {
   2782     //   SkASSERT(c0 <= c1 && c1 <= c2 && c2 <= c3);
   2783     SkASSERT(c0 < target && target < c3);
   2784 
   2785     SkScalar D = c0 - target;
   2786     SkScalar A = c3 + 3*(c1 - c2) - c0;
   2787     SkScalar B = 3*(c2 - c1 - c1 + c0);
   2788     SkScalar C = 3*(c1 - c0);
   2789 
   2790     const SkScalar TOLERANCE = SK_Scalar1 / 4096;
   2791     SkScalar minT = 0;
   2792     SkScalar maxT = SK_Scalar1;
   2793     SkScalar mid;
   2794     int i;
   2795     for (i = 0; i < 16; i++) {
   2796         mid = SkScalarAve(minT, maxT);
   2797         SkScalar delta = eval_cubic_coeff(A, B, C, D, mid);
   2798         if (delta < 0) {
   2799             minT = mid;
   2800             delta = -delta;
   2801         } else {
   2802             maxT = mid;
   2803         }
   2804         if (delta < TOLERANCE) {
   2805             break;
   2806         }
   2807     }
   2808     *t = mid;
   2809     return true;
   2810 }
   2811 
   2812 template <size_t N> static void find_minmax(const SkPoint pts[],
   2813                                             SkScalar* minPtr, SkScalar* maxPtr) {
   2814     SkScalar min, max;
   2815     min = max = pts[0].fX;
   2816     for (size_t i = 1; i < N; ++i) {
   2817         min = SkMinScalar(min, pts[i].fX);
   2818         max = SkMaxScalar(max, pts[i].fX);
   2819     }
   2820     *minPtr = min;
   2821     *maxPtr = max;
   2822 }
   2823 
   2824 static int winding_mono_cubic(const SkPoint pts[], SkScalar x, SkScalar y) {
   2825     SkPoint storage[4];
   2826 
   2827     int dir = 1;
   2828     if (pts[0].fY > pts[3].fY) {
   2829         storage[0] = pts[3];
   2830         storage[1] = pts[2];
   2831         storage[2] = pts[1];
   2832         storage[3] = pts[0];
   2833         pts = storage;
   2834         dir = -1;
   2835     }
   2836     if (y < pts[0].fY || y >= pts[3].fY) {
   2837         return 0;
   2838     }
   2839 
   2840     // quickreject or quickaccept
   2841     SkScalar min, max;
   2842     find_minmax<4>(pts, &min, &max);
   2843     if (x < min) {
   2844         return 0;
   2845     }
   2846     if (x > max) {
   2847         return dir;
   2848     }
   2849 
   2850     // compute the actual x(t) value
   2851     SkScalar t, xt;
   2852     if (chopMonoCubicAt(pts[0].fY, pts[1].fY, pts[2].fY, pts[3].fY, y, &t)) {
   2853         xt = eval_cubic_pts(pts[0].fX, pts[1].fX, pts[2].fX, pts[3].fX, t);
   2854     } else {
   2855         SkScalar mid = SkScalarAve(pts[0].fY, pts[3].fY);
   2856         xt = y < mid ? pts[0].fX : pts[3].fX;
   2857     }
   2858     return xt < x ? dir : 0;
   2859 }
   2860 
   2861 static int winding_cubic(const SkPoint pts[], SkScalar x, SkScalar y) {
   2862     SkPoint dst[10];
   2863     int n = SkChopCubicAtYExtrema(pts, dst);
   2864     int w = 0;
   2865     for (int i = 0; i <= n; ++i) {
   2866         w += winding_mono_cubic(&dst[i * 3], x, y);
   2867     }
   2868     return w;
   2869 }
   2870 
   2871 static int winding_mono_quad(const SkPoint pts[], SkScalar x, SkScalar y) {
   2872     SkScalar y0 = pts[0].fY;
   2873     SkScalar y2 = pts[2].fY;
   2874 
   2875     int dir = 1;
   2876     if (y0 > y2) {
   2877         SkTSwap(y0, y2);
   2878         dir = -1;
   2879     }
   2880     if (y < y0 || y >= y2) {
   2881         return 0;
   2882     }
   2883 
   2884     // bounds check on X (not required. is it faster?)
   2885 #if 0
   2886     if (pts[0].fX > x && pts[1].fX > x && pts[2].fX > x) {
   2887         return 0;
   2888     }
   2889 #endif
   2890 
   2891     SkScalar roots[2];
   2892     int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY,
   2893                                 2 * (pts[1].fY - pts[0].fY),
   2894                                 pts[0].fY - y,
   2895                                 roots);
   2896     SkASSERT(n <= 1);
   2897     SkScalar xt;
   2898     if (0 == n) {
   2899         SkScalar mid = SkScalarAve(y0, y2);
   2900         // Need [0] and [2] if dir == 1
   2901         // and  [2] and [0] if dir == -1
   2902         xt = y < mid ? pts[1 - dir].fX : pts[dir - 1].fX;
   2903     } else {
   2904         SkScalar t = roots[0];
   2905         SkScalar C = pts[0].fX;
   2906         SkScalar A = pts[2].fX - 2 * pts[1].fX + C;
   2907         SkScalar B = 2 * (pts[1].fX - C);
   2908         xt = SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C);
   2909     }
   2910     return xt < x ? dir : 0;
   2911 }
   2912 
   2913 static bool is_mono_quad(SkScalar y0, SkScalar y1, SkScalar y2) {
   2914     //    return SkScalarSignAsInt(y0 - y1) + SkScalarSignAsInt(y1 - y2) != 0;
   2915     if (y0 == y1) {
   2916         return true;
   2917     }
   2918     if (y0 < y1) {
   2919         return y1 <= y2;
   2920     } else {
   2921         return y1 >= y2;
   2922     }
   2923 }
   2924 
   2925 static int winding_quad(const SkPoint pts[], SkScalar x, SkScalar y) {
   2926     SkPoint dst[5];
   2927     int     n = 0;
   2928 
   2929     if (!is_mono_quad(pts[0].fY, pts[1].fY, pts[2].fY)) {
   2930         n = SkChopQuadAtYExtrema(pts, dst);
   2931         pts = dst;
   2932     }
   2933     int w = winding_mono_quad(pts, x, y);
   2934     if (n > 0) {
   2935         w += winding_mono_quad(&pts[2], x, y);
   2936     }
   2937     return w;
   2938 }
   2939 
   2940 static int winding_line(const SkPoint pts[], SkScalar x, SkScalar y) {
   2941     SkScalar x0 = pts[0].fX;
   2942     SkScalar y0 = pts[0].fY;
   2943     SkScalar x1 = pts[1].fX;
   2944     SkScalar y1 = pts[1].fY;
   2945 
   2946     SkScalar dy = y1 - y0;
   2947 
   2948     int dir = 1;
   2949     if (y0 > y1) {
   2950         SkTSwap(y0, y1);
   2951         dir = -1;
   2952     }
   2953     if (y < y0 || y >= y1) {
   2954         return 0;
   2955     }
   2956 
   2957     SkScalar cross = SkScalarMul(x1 - x0, y - pts[0].fY) -
   2958     SkScalarMul(dy, x - pts[0].fX);
   2959 
   2960     if (SkScalarSignAsInt(cross) == dir) {
   2961         dir = 0;
   2962     }
   2963     return dir;
   2964 }
   2965 
   2966 bool SkPath::contains(SkScalar x, SkScalar y) const {
   2967     bool isInverse = this->isInverseFillType();
   2968     if (this->isEmpty()) {
   2969         return isInverse;
   2970     }
   2971 
   2972     const SkRect& bounds = this->getBounds();
   2973     if (!bounds.contains(x, y)) {
   2974         return isInverse;
   2975     }
   2976 
   2977     SkPath::Iter iter(*this, true);
   2978     bool done = false;
   2979     int w = 0;
   2980     do {
   2981         SkPoint pts[4];
   2982         switch (iter.next(pts, false)) {
   2983             case SkPath::kMove_Verb:
   2984             case SkPath::kClose_Verb:
   2985                 break;
   2986             case SkPath::kLine_Verb:
   2987                 w += winding_line(pts, x, y);
   2988                 break;
   2989             case SkPath::kQuad_Verb:
   2990                 w += winding_quad(pts, x, y);
   2991                 break;
   2992             case SkPath::kConic_Verb:
   2993                 SkASSERT(0);
   2994                 break;
   2995             case SkPath::kCubic_Verb:
   2996                 w += winding_cubic(pts, x, y);
   2997                 break;
   2998             case SkPath::kDone_Verb:
   2999                 done = true;
   3000                 break;
   3001        }
   3002     } while (!done);
   3003 
   3004     switch (this->getFillType()) {
   3005         case SkPath::kEvenOdd_FillType:
   3006         case SkPath::kInverseEvenOdd_FillType:
   3007             w &= 1;
   3008             break;
   3009         default:
   3010             break;
   3011     }
   3012     return SkToBool(w);
   3013 }
   3014