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