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