Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkPath.cpp
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  */
25 static 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
32 static 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
38 class SkAutoDisableDirectionCheck {
39 public:
40     SkAutoDisableDirectionCheck(SkPath* path) : fPath(path) {
41         fSaved = static_cast<SkPath::Direction>(fPath->fDirection);
42     }
43
44     ~SkAutoDisableDirectionCheck() {
45         fPath->fDirection = fSaved;
46     }
47
48 private:
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  */
66 class SkAutoPathBoundsUpdate {
67 public:
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
86 private:
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
128 SkPath::SkPath()
129     : fPathRef(SkPathRef::CreateEmpty())
130 #ifdef SK_BUILD_FOR_ANDROID
131     , fSourcePath(NULL)
132 #endif
133 {
134     this->resetFields();
135 }
136
137 void 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
148 SkPath::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
157 SkPath::~SkPath() {
158     SkDEBUGCODE(this->validate();)
159 }
160
161 SkPath& 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
175 void 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
183 bool 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
190 void 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
205 static 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
231 bool 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
292 uint32_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
302 const SkPath* SkPath::getSourcePath() const {
303     return fSourcePath;
304 }
305
306 void SkPath::setSourcePath(const SkPath* path) {
307     fSourcePath = path;
308 }
309 #endif
310
311 void SkPath::reset() {
312     SkDEBUGCODE(this->validate();)
313
314     fPathRef.reset(SkPathRef::CreateEmpty());
315     this->resetFields();
316 }
317
318 void SkPath::rewind() {
319     SkDEBUGCODE(this->validate();)
320
321     SkPathRef::Rewind(&fPathRef);
322     this->resetFields();
323 }
324
325 bool 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
353 A rectangle cycles up/right/down/left or up/left/down/right.
354
355 The 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
370 It's OK if the path has:
371   Several colinear line segments composing a rectangle side.
372   Single points on the rectangle side.
373
374 The direction takes advantage of the corners found since opposite sides
375 must travel in opposite directions.
376
377 FIXME: Allow colinear quads and cubics to be treated like lines.
378 FIXME: 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  */
389 static int rect_make_dir(SkScalar dx, SkScalar dy) {
390     return ((0 != dx) << 0) | ((dx > 0 || dy > 0) << 1);
391 }
392 bool 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
507 SkPath::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
515 bool 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
526 bool 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
533 bool 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
573 int SkPath::countPoints() const {
574     return fPathRef->countPoints();
575 }
576
577 int 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
587 SkPoint 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
594 int SkPath::countVerbs() const {
595     return fPathRef->countVerbs();
596 }
597
598 static 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
606 int 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
616 bool 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
632 void 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
644 void 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
659 void SkPath::incReserve(U16CPU inc) {
660     SkDEBUGCODE(this->validate();)
661     SkPathRef::Editor(&fPathRef, inc, inc);
662     SkDEBUGCODE(this->validate();)
663 }
664
665 void 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
678 void SkPath::rMoveTo(SkScalar x, SkScalar y) {
679     SkPoint pt;
680     this->getLastPt(&pt);
681     this->moveTo(pt.fX + x, pt.fY + y);
682 }
683
684 void 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
698 void 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
709 void 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
716 void 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
729 void 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
736 void 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
760 void 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
768 void 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
783 void 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
792 void 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
828 static void assert_known_direction(int dir) {
829     SkASSERT(SkPath::kCW_Direction == dir || SkPath::kCCW_Direction == dir);
830 }
831
832 void SkPath::addRect(const SkRect& rect, Direction dir) {
833     this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir);
834 }
835
836 void 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
859 void 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
886 static 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
947 void 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.
956 Clockwise                                                     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
981 Counterclockwise
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 */
1006 static 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
1081 void 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
1120 bool 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
1135 void 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
1152 void 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
1221 void 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
1229 void 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
1249 void 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 */
1285 void 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
1352 void 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
1359 void 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
1407 static 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
1423 void 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
1470 void 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
1523 void 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
1532 static 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
1545 static 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
1558 void 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
1634 enum 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
1643 SkPath::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
1657 SkPath::Iter::Iter(const SkPath& path, bool forceClose) {
1658     this->setPath(path, forceClose);
1659 }
1660
1661 void 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
1673 bool 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
1701 SkPath::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
1723 const 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
1735 void 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
1813 SkPath::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
1892 SkPath::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
1903 SkPath::RawIter::RawIter(const SkPath& path) {
1904     this->setPath(path);
1905 }
1906
1907 void 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
1916 SkPath::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
1969 size_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
1991 size_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
2022 static 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
2035 static 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
2056 void 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
2099 void SkPath::dump() const {
2100     this->dump(NULL, false, false);
2101 }
2102
2103 void SkPath::dumpHex() const {
2104     this->dump(NULL, false, true);
2105 }
2106
2107 #ifdef SK_DEBUG
2108 void 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
2142 static int sign(SkScalar x) { return x < 0; }
2143 #define kValueNeverReturnedBySign   2
2144
2145 enum DirChange {
2146     kLeft_DirChange,
2147     kRight_DirChange,
2148     kStraight_DirChange,
2149     kBackwards_DirChange,
2150
2151     kInvalid_DirChange
2152 };
2153
2154
2155 static 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
2169 static 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
2194 struct 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
2255 private:
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
2295 SkPath::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
2347 class ContourIter {
2348 public:
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
2357 private:
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
2367 ContourIter::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
2378 void 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     }
2416 CONTOUR_END:
2417     fCurrPtCount = ptCount;
2418     fCurrVerb = verbs;
2419     SkDEBUGCODE(++fContourCounter;)
2420 }
2421
2422 // returns cross product of (p1 - p0) and (p2 - p0)
2423 static 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
2445 static 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
2459 static 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  */
2477 static 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
2501 static 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  */
2513 bool 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
2605 static 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
2610 static 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  */
2622 static 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
2653 template <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
2665 static 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
2698 static 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
2708 static 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
2750 static 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
2762 static 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
2777 static 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
2803 static 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
2807 bool 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 }