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