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