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