1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPathMakers_DEFINED
9 #define SkPathMakers_DEFINED
10 
11 #include "include/core/SkPath.h"    // just for direction
12 #include "include/core/SkPoint.h"
13 #include "include/core/SkRRect.h"
14 
15 template <unsigned N> class SkPath_PointIterator {
16 public:
SkPath_PointIterator(SkPath::Direction dir,unsigned startIndex)17     SkPath_PointIterator(SkPath::Direction dir, unsigned startIndex)
18     : fCurrent(startIndex % N)
19     , fAdvance(dir == SkPath::kCW_Direction ? 1 : N - 1) { }
20 
current()21     const SkPoint& current() const {
22         SkASSERT(fCurrent < N);
23         return fPts[fCurrent];
24     }
25 
next()26     const SkPoint& next() {
27         fCurrent = (fCurrent + fAdvance) % N;
28         return this->current();
29     }
30 
31     protected:
32     SkPoint fPts[N];
33 
34     private:
35     unsigned fCurrent;
36     unsigned fAdvance;
37 };
38 
39 class SkPath_RectPointIterator : public SkPath_PointIterator<4> {
40 public:
SkPath_RectPointIterator(const SkRect & rect,SkPath::Direction dir,unsigned startIndex)41     SkPath_RectPointIterator(const SkRect& rect, SkPath::Direction dir, unsigned startIndex)
42         : SkPath_PointIterator(dir, startIndex) {
43 
44         fPts[0] = SkPoint::Make(rect.fLeft, rect.fTop);
45         fPts[1] = SkPoint::Make(rect.fRight, rect.fTop);
46         fPts[2] = SkPoint::Make(rect.fRight, rect.fBottom);
47         fPts[3] = SkPoint::Make(rect.fLeft, rect.fBottom);
48     }
49 };
50 
51 class SkPath_OvalPointIterator : public SkPath_PointIterator<4> {
52 public:
SkPath_OvalPointIterator(const SkRect & oval,SkPath::Direction dir,unsigned startIndex)53     SkPath_OvalPointIterator(const SkRect& oval, SkPath::Direction dir, unsigned startIndex)
54         : SkPath_PointIterator(dir, startIndex) {
55 
56         const SkScalar cx = oval.centerX();
57         const SkScalar cy = oval.centerY();
58 
59         fPts[0] = SkPoint::Make(cx, oval.fTop);
60         fPts[1] = SkPoint::Make(oval.fRight, cy);
61         fPts[2] = SkPoint::Make(cx, oval.fBottom);
62         fPts[3] = SkPoint::Make(oval.fLeft, cy);
63     }
64 };
65 
66 class SkPath_RRectPointIterator : public SkPath_PointIterator<8> {
67 public:
SkPath_RRectPointIterator(const SkRRect & rrect,SkPath::Direction dir,unsigned startIndex)68     SkPath_RRectPointIterator(const SkRRect& rrect, SkPath::Direction dir, unsigned startIndex)
69         : SkPath_PointIterator(dir, startIndex) {
70 
71         const SkRect& bounds = rrect.getBounds();
72         const SkScalar L = bounds.fLeft;
73         const SkScalar T = bounds.fTop;
74         const SkScalar R = bounds.fRight;
75         const SkScalar B = bounds.fBottom;
76 
77         fPts[0] = SkPoint::Make(L + rrect.radii(SkRRect::kUpperLeft_Corner).fX, T);
78         fPts[1] = SkPoint::Make(R - rrect.radii(SkRRect::kUpperRight_Corner).fX, T);
79         fPts[2] = SkPoint::Make(R, T + rrect.radii(SkRRect::kUpperRight_Corner).fY);
80         fPts[3] = SkPoint::Make(R, B - rrect.radii(SkRRect::kLowerRight_Corner).fY);
81         fPts[4] = SkPoint::Make(R - rrect.radii(SkRRect::kLowerRight_Corner).fX, B);
82         fPts[5] = SkPoint::Make(L + rrect.radii(SkRRect::kLowerLeft_Corner).fX, B);
83         fPts[6] = SkPoint::Make(L, B - rrect.radii(SkRRect::kLowerLeft_Corner).fY);
84         fPts[7] = SkPoint::Make(L, T + rrect.radii(SkRRect::kUpperLeft_Corner).fY);
85     }
86 };
87 
88 #endif
89