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