blob: f9b32ea4170ef7161045baff4485b65c4918f486 [file] [log] [blame]
mike@reedtribe.orgb5637092012-12-22 20:53:59 +00001/*
2 * Copyright 2012 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#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "SkRandom.h"
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000012#include "SkRRect.h"
13#include "SkColorPriv.h"
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000014
15static void rotateAbout(SkCanvas* canvas, SkScalar degrees,
16 SkScalar cx, SkScalar cy) {
17 canvas->translate(cx, cy);
18 canvas->rotate(degrees);
19 canvas->translate(-cx, -cy);
20}
21
22class RotateCirclesView : public SampleView {
23public:
24 RotateCirclesView() {
25 this->setBGColor(SK_ColorLTGRAY);
skia.committer@gmail.com15ed90f2012-12-23 02:01:31 +000026
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000027 fAngle = 0;
28 }
29
30protected:
31 // overrides from SkEventSink
32 virtual bool onQuery(SkEvent* evt) {
33 if (SampleCode::TitleQ(*evt)) {
34 SampleCode::TitleR(evt, "RotateCircles");
35 return true;
36 }
37 return this->INHERITED::onQuery(evt);
38 }
39
40 virtual void onDrawContent(SkCanvas* canvas) {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +000041 SkRandom rand;
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000042 SkPaint paint;
43 paint.setAntiAlias(true);
44 paint.setStrokeWidth(20);
45
46 SkScalar cx = 240;
47 SkScalar cy = 240;
48 SkScalar DX = 240 * 2;
49 SkColor color = 0;
50
51 float scale = 1;
52 float sign = 0.3f;
53 for (SkScalar rad = 200; rad >= 20; rad -= 15) {
54 sign = -sign;
55 scale += 0.2f;
56
57 paint.setColor(rand.nextU());
58 paint.setAlpha(0xFF);
59 color = ~color;
skia.committer@gmail.com15ed90f2012-12-23 02:01:31 +000060
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000061 paint.setStyle(SkPaint::kFill_Style);
62
63 canvas->save();
64 rotateAbout(canvas, fAngle * scale * sign, cx, cy);
65 canvas->drawCircle(cx, cy, rad, paint);
66 canvas->restore();
67
68 paint.setStyle(SkPaint::kStroke_Style);
69 paint.setStrokeWidth(rad*2);
skia.committer@gmail.com21579832012-12-25 02:01:27 +000070
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000071 canvas->save();
72 rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy);
73 canvas->drawCircle(cx + DX, cy, 10, paint);
74 canvas->restore();
skia.committer@gmail.com15ed90f2012-12-23 02:01:31 +000075
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000076 canvas->save();
77 rotateAbout(canvas, fAngle * scale * sign, cx + DX, cy + DX);
78 canvas->drawCircle(cx + DX, cy + DX, 10, paint);
79 canvas->restore();
skia.committer@gmail.com21579832012-12-25 02:01:27 +000080
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000081 }
skia.committer@gmail.com15ed90f2012-12-23 02:01:31 +000082
mike@reedtribe.orgb5637092012-12-22 20:53:59 +000083 fAngle = (fAngle + 1) % 360;
84 this->inval(NULL);
85 }
86
87private:
88 int fAngle;
89 typedef SkView INHERITED;
90};
91
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000092class TestCirclesView : public SampleView {
93public:
94 TestCirclesView() {
95 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +000096
mike@reedtribe.org61490fa2012-12-24 14:38:46 +000097protected:
98 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
99 if (SampleCode::TitleQ(*evt)) {
100 SampleCode::TitleR(evt, "RotateCircles2");
101 return true;
102 }
103 return this->INHERITED::onQuery(evt);
104 }
105
106 void draw_real_circle(SkCanvas* canvas, SkScalar radius) {
107 int w = SkScalarCeilToInt(radius * 2);
108 int h = w;
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000109
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000110 SkBitmap bm;
commit-bot@chromium.orga8c18312014-02-17 02:55:57 +0000111 bm.allocN32Pixels(w, h);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000112 bm.eraseColor(0);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000113
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000114 SkAutoLockPixels alp(bm);
115
116 SkScalar cx = radius;
117 SkScalar cy = radius;
118 for (int y = 0; y < h; y += 1) {
119 for (int x = 0; x < w; x += 1) {
120 float d = sqrtf((x - cx)*(x - cx) + (y - cy)*(y - cy));
121 if (d <= radius) {
122 *bm.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0, 0);
123 }
124 }
125 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000126
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000127 canvas->drawBitmap(bm, 0, 0, NULL);
128 }
129
130 virtual void onDrawContent(SkCanvas* canvas) {
131 SkScalar radius = 256;
132 canvas->translate(10, 10);
133
134 draw_real_circle(canvas, radius);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000135
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000136 SkPaint paint;
137 paint.setAntiAlias(true);
138
139 paint.setColor(0x80FF0000);
140 canvas->drawCircle(radius, radius, radius, paint);
141
142 paint.setStyle(SkPaint::kStroke_Style);
143 paint.setStrokeWidth(radius);
144 paint.setColor(0x8000FF00);
145 canvas->drawCircle(radius, radius, radius/2, paint);
146 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000147
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000148private:
149 typedef SkView INHERITED;
150};
151
152static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
153 const SkScalar TOL = 7;
154 return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL;
155}
156
157static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
158 SkPath::RawIter iter(path);
159 SkPoint pts[4];
160 SkPath::Verb verb;
161
162 int count = 0;
163 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
164 switch (verb) {
165 case SkPath::kMove_Verb:
166 case SkPath::kLine_Verb:
167 case SkPath::kQuad_Verb:
168 case SkPath::kCubic_Verb:
169 storage[count++] = pts[0];
170 break;
171 default:
172 break;
173 }
174 }
175 return count;
176}
177
178#include "SkPathMeasure.h"
179
180class TestStrokeView : public SampleView {
181 enum {
182 SKELETON_COLOR = 0xFF0000FF,
183 WIREFRAME_COLOR = 0x80FF0000
184 };
185
186 enum {
187 kCount = 9
188 };
189 SkPoint fPts[kCount];
190 SkScalar fWidth, fDWidth;
191public:
192 TestStrokeView() {
193 this->setBGColor(SK_ColorLTGRAY);
194
195 fPts[0].set(50, 200);
196 fPts[1].set(50, 100);
197 fPts[2].set(150, 50);
198 fPts[3].set(300, 50);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000199
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000200 fPts[4].set(350, 200);
201 fPts[5].set(350, 100);
202 fPts[6].set(450, 50);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000203
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000204 fPts[7].set(200, 200);
205 fPts[8].set(400, 400);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000206
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000207 fWidth = 50;
208 fDWidth = 0.25f;
209 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000210
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000211protected:
212 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
213 if (SampleCode::TitleQ(*evt)) {
214 SampleCode::TitleR(evt, "RotateCircles3");
215 return true;
216 }
217 return this->INHERITED::onQuery(evt);
218 }
219
220 void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color,
221 bool show_lines) {
222 SkPaint paint;
223 paint.setColor(color);
224 paint.setAlpha(0x80);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000225
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000226 int n = path.countPoints();
227 SkAutoSTArray<32, SkPoint> pts(n);
228 if (show_lines) {
229 path.getPoints(pts.get(), n);
230 canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint);
231 } else {
232 n = getOnCurvePoints(path, pts.get());
233 }
234 paint.setStrokeWidth(5);
235 canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint);
236 }
237
238 void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width,
239 SkColor color) {
240 const SkScalar radius = width / 2;
241
242 SkPathMeasure meas(path, false);
243 SkScalar total = meas.getLength();
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000244
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000245 SkScalar delta = 8;
246 SkPaint paint;
247 paint.setColor(color);
248
249 SkPoint pos, tan;
250 for (SkScalar dist = 0; dist <= total; dist += delta) {
reed@google.com140d7282013-01-07 20:25:04 +0000251 if (meas.getPosTan(dist, &pos, &tan)) {
252 tan.scale(radius);
253 tan.rotateCCW();
254 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
255 pos.x() - tan.x(), pos.y() - tan.y(), paint);
256 }
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000257 }
258 }
259
260 void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width) {
261 SkPaint paint;
262 paint.setAntiAlias(true);
263 paint.setStyle(SkPaint::kStroke_Style);
264
265 paint.setColor(SKELETON_COLOR);
266 canvas->drawPath(path, paint);
267 draw_points(canvas, path, SKELETON_COLOR, true);
268
269 draw_ribs(canvas, path, width, 0xFF00FF00);
270
271 SkPath fill;
272
273 SkPaint p;
274 p.setStyle(SkPaint::kStroke_Style);
275 p.setStrokeWidth(width);
276 p.getFillPath(path, &fill);
277
278 paint.setColor(WIREFRAME_COLOR);
279 canvas->drawPath(fill, paint);
280 draw_points(canvas, fill, WIREFRAME_COLOR, false);
281 }
282
283 virtual void onDrawContent(SkCanvas* canvas) {
284 SkPath path;
285 SkScalar width = fWidth;
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000286
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000287 path.moveTo(fPts[0]);
288 path.cubicTo(fPts[1], fPts[2], fPts[3]);
289 draw_stroke(canvas, path, width);
290
291 path.reset();
292 path.moveTo(fPts[4]);
293 path.quadTo(fPts[5], fPts[6]);
294 draw_stroke(canvas, path, width);
295
296 SkScalar rad = 32;
297 SkRect r;
298 r.set(&fPts[7], 2);
299 path.reset();
300 SkRRect rr;
301 rr.setRectXY(r, rad, rad);
302 path.addRRect(rr);
303 draw_stroke(canvas, path, width);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000304
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000305 path.reset();
306 SkRRect rr2;
307 rr.inset(width/2, width/2, &rr2);
308 path.addRRect(rr2, SkPath::kCCW_Direction);
309 rr.inset(-width/2, -width/2, &rr2);
310 path.addRRect(rr2, SkPath::kCW_Direction);
311 SkPaint paint;
312 paint.setAntiAlias(true);
313 paint.setColor(0x40FF8844);
314 canvas->drawPath(path, paint);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000315
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000316 fWidth += fDWidth;
317 if (fDWidth > 0 && fWidth > 100) {
318 fDWidth = -fDWidth;
319 } else if (fDWidth < 0 && fWidth < 10) {
320 fDWidth = -fDWidth;
321 }
322 this->inval(NULL);
323 }
324
325 class MyClick : public Click {
326 public:
327 int fIndex;
328 MyClick(SkView* target, int index) : Click(target), fIndex(index) {}
329 };
330
reed@google.com4d5c26d2013-01-08 16:17:50 +0000331 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
332 unsigned modi) SK_OVERRIDE {
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000333 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) {
334 if (hittest(fPts[i], x, y)) {
reed@google.com7fa2a652014-01-27 13:42:58 +0000335 return new MyClick(this, (int)i);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000336 }
337 }
reed@google.com4d5c26d2013-01-08 16:17:50 +0000338 return this->INHERITED::onFindClickHandler(x, y, modi);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000339 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000340
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000341 virtual bool onClick(Click* click) {
342 int index = ((MyClick*)click)->fIndex;
jvanverth@google.com9c81bd52013-01-03 14:46:41 +0000343 fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX),
344 SkIntToScalar(click->fICurr.fY - click->fIPrev.fY));
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000345 this->inval(NULL);
346 return true;
347 }
348
349private:
350 typedef SkView INHERITED;
351};
352
353///////////////////////////////////////////////////////////////////////////////
354
mike@reedtribe.orgb5637092012-12-22 20:53:59 +0000355static SkView* F0() { return new RotateCirclesView; }
356static SkViewRegister gR0(F0);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000357static SkView* F1() { return new TestCirclesView; }
358static SkViewRegister gR1(F1);
359static SkView* F2() { return new TestStrokeView; }
360static SkViewRegister gR2(F2);