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