blob: ebe715d8665775729833b430d531a1a2bec1deeb [file] [log] [blame]
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001
2/*
3 * Copyright 2011 Google Inc.
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#include "gm.h"
9#include "SkRandom.h"
10#include "SkTArray.h"
11
reed@google.comd42e3f62012-03-30 20:04:21 +000012class SkOnce : SkNoncopyable {
13public:
14 SkOnce() { fDidOnce = false; }
15
16 bool needToDo() const { return !fDidOnce; }
17 bool alreadyDone() const { return fDidOnce; }
18 void accomplished() {
19 SkASSERT(!fDidOnce);
20 fDidOnce = true;
21 }
22
23private:
24 bool fDidOnce;
25};
26
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000027namespace skiagm {
28
29class ConvexPathsGM : public GM {
reed@google.comd42e3f62012-03-30 20:04:21 +000030 SkOnce fOnce;
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000031public:
32 ConvexPathsGM() {
bsalomon@google.com72b55be2012-01-26 20:33:19 +000033 this->setBGColor(0xFF000000);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000034 }
35
36protected:
37 virtual SkString onShortName() {
38 return SkString("convexpaths");
39 }
40
41
42 virtual SkISize onISize() {
43 return make_isize(1200, 900);
44 }
45
46 void makePaths() {
reed@google.comd42e3f62012-03-30 20:04:21 +000047 if (fOnce.alreadyDone()) {
48 return;
49 }
50 fOnce.accomplished();
51
bsalomon@google.com278dc692012-02-15 16:52:51 +000052 // CW
53 fPaths.push_back().moveTo(0, 0);
54 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
55 0, 100 * SK_Scalar1);
56 fPaths.back().lineTo(0, 0);
57
58 // CCW
59 fPaths.push_back().moveTo(0, 0);
60 fPaths.back().lineTo(0, 100 * SK_Scalar1);
61 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
62 0, 0);
63
64 // CW
65 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
66 fPaths.back().quadTo(50 * SK_Scalar1, 0,
67 100 * SK_Scalar1, 50 * SK_Scalar1);
68 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
69 0, 50 * SK_Scalar1);
70
71 // CCW
72 fPaths.push_back().moveTo(0, 50 * SK_Scalar1);
73 fPaths.back().quadTo(50 * SK_Scalar1, 100 * SK_Scalar1,
74 100 * SK_Scalar1, 50 * SK_Scalar1);
75 fPaths.back().quadTo(50 * SK_Scalar1, 0,
76 0, 50 * SK_Scalar1);
77
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +000078 fPaths.push_back().addRect(0, 0,
79 100 * SK_Scalar1, 100 * SK_Scalar1,
80 SkPath::kCW_Direction);
81
82 fPaths.push_back().addRect(0, 0,
83 100 * SK_Scalar1, 100 * SK_Scalar1,
84 SkPath::kCCW_Direction);
85
86 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
87 50 * SK_Scalar1, SkPath::kCW_Direction);
88
89 fPaths.push_back().addCircle(50 * SK_Scalar1, 50 * SK_Scalar1,
90 40 * SK_Scalar1, SkPath::kCCW_Direction);
91
92 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
93 50 * SK_Scalar1,
94 100 * SK_Scalar1),
95 SkPath::kCW_Direction);
96
97 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
98 100 * SK_Scalar1,
99 50 * SK_Scalar1),
100 SkPath::kCCW_Direction);
101
102 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
103 100 * SK_Scalar1,
104 5 * SK_Scalar1),
105 SkPath::kCCW_Direction);
106
107 fPaths.push_back().addOval(SkRect::MakeXYWH(0, 0,
108 SK_Scalar1,
109 100 * SK_Scalar1),
110 SkPath::kCCW_Direction);
111
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000112 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
113 SK_Scalar1 * 100,
114 SK_Scalar1 * 100),
115 40 * SK_Scalar1, 20 * SK_Scalar1,
116 SkPath::kCW_Direction);
117
118 fPaths.push_back().addRoundRect(SkRect::MakeXYWH(0, 0,
119 SK_Scalar1 * 100,
120 SK_Scalar1 * 100),
121 20 * SK_Scalar1, 40 * SK_Scalar1,
122 SkPath::kCCW_Direction);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000123
124 // shallow diagonals
125 fPaths.push_back().lineTo(100 * SK_Scalar1, SK_Scalar1);
126 fPaths.back().lineTo(98 * SK_Scalar1, 100 * SK_Scalar1);
127 fPaths.back().lineTo(3 * SK_Scalar1, 96 * SK_Scalar1);
bsalomon@google.com9732f622012-01-31 15:19:21 +0000128
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000129 /*
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000130 It turns out arcTos are not automatically marked as convex and they
131 may in fact be ever so slightly concave.
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000132 fPaths.push_back().arcTo(SkRect::MakeXYWH(0, 0,
133 50 * SK_Scalar1,
134 100 * SK_Scalar1),
135 25 * SK_Scalar1, 130 * SK_Scalar1, false);
136 */
137
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000138 // cubics
139 fPaths.push_back().cubicTo( 1 * SK_Scalar1, 1 * SK_Scalar1,
140 10 * SK_Scalar1, 90 * SK_Scalar1,
141 0 * SK_Scalar1, 100 * SK_Scalar1);
142 fPaths.push_back().cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
143 20 * SK_Scalar1, 100 * SK_Scalar1,
144 0 * SK_Scalar1, 0 * SK_Scalar1);
145
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000146 // triangle where one edge is a degenerate quad
147 fPaths.push_back().moveTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
148 fPaths.back().quadTo(SkFloatToScalar(16.9921875f), 45 * SK_Scalar1,
149 SkFloatToScalar(31.25f), 45 * SK_Scalar1);
150 fPaths.back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
151 fPaths.back().lineTo(SkFloatToScalar(8.59375f), 45 * SK_Scalar1);
152
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000153 // point degenerate
bsalomon@google.com5cc90d12012-01-17 16:28:34 +0000154 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
155 fPaths.back().lineTo(50 * SK_Scalar1, 50 * SK_Scalar1);
156
157 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
158 fPaths.back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
159 50 * SK_Scalar1, 50 * SK_Scalar1);
160 fPaths.push_back().moveTo(50 * SK_Scalar1, 50 * SK_Scalar1);
161 fPaths.back().cubicTo(50 * SK_Scalar1, 50 * SK_Scalar1,
162 50 * SK_Scalar1, 50 * SK_Scalar1,
163 50 * SK_Scalar1, 50 * SK_Scalar1);
bsalomon@google.comdc3c7802012-01-31 20:46:32 +0000164
bsalomon@google.com9732f622012-01-31 15:19:21 +0000165 // moveTo only paths
166 fPaths.push_back().moveTo(0, 0);
167 fPaths.back().moveTo(0, 0);
168 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
169 fPaths.back().moveTo(SK_Scalar1, SK_Scalar1);
170 fPaths.back().moveTo(10 * SK_Scalar1, 10 * SK_Scalar1);
171
172 fPaths.push_back().moveTo(0, 0);
173 fPaths.back().moveTo(0, 0);
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000174
175 // line degenerate
176 fPaths.push_back().lineTo(100 * SK_Scalar1, 100 * SK_Scalar1);
177 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1, 0, 0);
178 fPaths.push_back().quadTo(100 * SK_Scalar1, 100 * SK_Scalar1,
179 50 * SK_Scalar1, 50 * SK_Scalar1);
180 fPaths.push_back().quadTo(50 * SK_Scalar1, 50 * SK_Scalar1,
181 100 * SK_Scalar1, 100 * SK_Scalar1);
182 fPaths.push_back().cubicTo(0, 0,
183 0, 0,
184 100 * SK_Scalar1, 100 * SK_Scalar1);
bsalomon@google.com5b56d9e2012-02-23 19:18:37 +0000185
186 // small circle. This is listed last so that it has device coords far
187 // from the origin (small area relative to x,y values).
188 fPaths.push_back().addCircle(0, 0, SkFloatToScalar(0.8f));
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000189 }
190
191 virtual void onDraw(SkCanvas* canvas) {
reed@google.comd42e3f62012-03-30 20:04:21 +0000192 this->makePaths();
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000193
194 SkPaint paint;
195 paint.setAntiAlias(true);
196 SkRandom rand;
197 canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1);
bsalomon@google.com72b55be2012-01-26 20:33:19 +0000198 for (int i = 0; i < fPaths.count(); ++i) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000199 canvas->save();
200 // position the path, and make it at off-integer coords.
201 canvas->translate(SK_Scalar1 * 200 * (i % 5) + SK_Scalar1 / 4,
202 SK_Scalar1 * 200 * (i / 5) + 3 * SK_Scalar1 / 4);
203 SkColor color = rand.nextU();
204 color |= 0xff000000;
205 paint.setColor(color);
206 SkASSERT(fPaths[i].isConvex());
207 canvas->drawPath(fPaths[i], paint);
208 canvas->restore();
209 }
210 }
211
212private:
213 typedef GM INHERITED;
214 SkTArray<SkPath> fPaths;
215};
216
217//////////////////////////////////////////////////////////////////////////////
218
219static GM* MyFactory(void*) { return new ConvexPathsGM; }
220static GMRegistry reg(MyFactory);
221
222}
223