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/SkPathTypes.h"
12#include "include/core/SkPoint.h"
13#include "include/core/SkRRect.h"
14
15template <unsigned N> class SkPath_PointIterator {
16public:
17 SkPath_PointIterator(SkPathDirection dir, unsigned startIndex)
18 : fCurrent(startIndex % N)
19 , fAdvance(dir == SkPathDirection::kCW ? 1 : N - 1) { }
20
21 const SkPoint& current() const {
22 SkASSERT(fCurrent < N);
23 return fPts[fCurrent];
24 }
25
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
39class SkPath_RectPointIterator : public SkPath_PointIterator<4> {
40public:
41 SkPath_RectPointIterator(const SkRect& rect, SkPathDirection 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
51class SkPath_OvalPointIterator : public SkPath_PointIterator<4> {
52public:
53 SkPath_OvalPointIterator(const SkRect& oval, SkPathDirection 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
66class SkPath_RRectPointIterator : public SkPath_PointIterator<8> {
67public:
68 SkPath_RRectPointIterator(const SkRRect& rrect, SkPathDirection 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