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