blob: 1f586be4fecaf20932a8ea4a3574dd127a379482 [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;
111 bm.setConfig(SkBitmap::kARGB_8888_Config, w, h);
112 bm.allocPixels();
113 bm.eraseColor(0);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000114
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000115 SkAutoLockPixels alp(bm);
116
117 SkScalar cx = radius;
118 SkScalar cy = radius;
119 for (int y = 0; y < h; y += 1) {
120 for (int x = 0; x < w; x += 1) {
121 float d = sqrtf((x - cx)*(x - cx) + (y - cy)*(y - cy));
122 if (d <= radius) {
123 *bm.getAddr32(x, y) = SkPackARGB32(0xFF, 0, 0, 0);
124 }
125 }
126 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000127
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000128 canvas->drawBitmap(bm, 0, 0, NULL);
129 }
130
131 virtual void onDrawContent(SkCanvas* canvas) {
132 SkScalar radius = 256;
133 canvas->translate(10, 10);
134
135 draw_real_circle(canvas, radius);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000136
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000137 SkPaint paint;
138 paint.setAntiAlias(true);
139
140 paint.setColor(0x80FF0000);
141 canvas->drawCircle(radius, radius, radius, paint);
142
143 paint.setStyle(SkPaint::kStroke_Style);
144 paint.setStrokeWidth(radius);
145 paint.setColor(0x8000FF00);
146 canvas->drawCircle(radius, radius, radius/2, paint);
147 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000148
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000149private:
150 typedef SkView INHERITED;
151};
152
153static bool hittest(const SkPoint& target, SkScalar x, SkScalar y) {
154 const SkScalar TOL = 7;
155 return SkPoint::Distance(target, SkPoint::Make(x, y)) <= TOL;
156}
157
158static int getOnCurvePoints(const SkPath& path, SkPoint storage[]) {
159 SkPath::RawIter iter(path);
160 SkPoint pts[4];
161 SkPath::Verb verb;
162
163 int count = 0;
164 while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
165 switch (verb) {
166 case SkPath::kMove_Verb:
167 case SkPath::kLine_Verb:
168 case SkPath::kQuad_Verb:
169 case SkPath::kCubic_Verb:
170 storage[count++] = pts[0];
171 break;
172 default:
173 break;
174 }
175 }
176 return count;
177}
178
179#include "SkPathMeasure.h"
180
181class TestStrokeView : public SampleView {
182 enum {
183 SKELETON_COLOR = 0xFF0000FF,
184 WIREFRAME_COLOR = 0x80FF0000
185 };
186
187 enum {
188 kCount = 9
189 };
190 SkPoint fPts[kCount];
191 SkScalar fWidth, fDWidth;
192public:
193 TestStrokeView() {
194 this->setBGColor(SK_ColorLTGRAY);
195
196 fPts[0].set(50, 200);
197 fPts[1].set(50, 100);
198 fPts[2].set(150, 50);
199 fPts[3].set(300, 50);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000200
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000201 fPts[4].set(350, 200);
202 fPts[5].set(350, 100);
203 fPts[6].set(450, 50);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000204
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000205 fPts[7].set(200, 200);
206 fPts[8].set(400, 400);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000207
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000208 fWidth = 50;
209 fDWidth = 0.25f;
210 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000211
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000212protected:
213 virtual bool onQuery(SkEvent* evt) SK_OVERRIDE {
214 if (SampleCode::TitleQ(*evt)) {
215 SampleCode::TitleR(evt, "RotateCircles3");
216 return true;
217 }
218 return this->INHERITED::onQuery(evt);
219 }
220
221 void draw_points(SkCanvas* canvas, const SkPath& path, SkColor color,
222 bool show_lines) {
223 SkPaint paint;
224 paint.setColor(color);
225 paint.setAlpha(0x80);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000226
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000227 int n = path.countPoints();
228 SkAutoSTArray<32, SkPoint> pts(n);
229 if (show_lines) {
230 path.getPoints(pts.get(), n);
231 canvas->drawPoints(SkCanvas::kPolygon_PointMode, n, pts.get(), paint);
232 } else {
233 n = getOnCurvePoints(path, pts.get());
234 }
235 paint.setStrokeWidth(5);
236 canvas->drawPoints(SkCanvas::kPoints_PointMode, n, pts.get(), paint);
237 }
238
239 void draw_ribs(SkCanvas* canvas, const SkPath& path, SkScalar width,
240 SkColor color) {
241 const SkScalar radius = width / 2;
242
243 SkPathMeasure meas(path, false);
244 SkScalar total = meas.getLength();
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000245
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000246 SkScalar delta = 8;
247 SkPaint paint;
248 paint.setColor(color);
249
250 SkPoint pos, tan;
251 for (SkScalar dist = 0; dist <= total; dist += delta) {
reed@google.com140d7282013-01-07 20:25:04 +0000252 if (meas.getPosTan(dist, &pos, &tan)) {
253 tan.scale(radius);
254 tan.rotateCCW();
255 canvas->drawLine(pos.x() + tan.x(), pos.y() + tan.y(),
256 pos.x() - tan.x(), pos.y() - tan.y(), paint);
257 }
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000258 }
259 }
260
261 void draw_stroke(SkCanvas* canvas, const SkPath& path, SkScalar width) {
262 SkPaint paint;
263 paint.setAntiAlias(true);
264 paint.setStyle(SkPaint::kStroke_Style);
265
266 paint.setColor(SKELETON_COLOR);
267 canvas->drawPath(path, paint);
268 draw_points(canvas, path, SKELETON_COLOR, true);
269
270 draw_ribs(canvas, path, width, 0xFF00FF00);
271
272 SkPath fill;
273
274 SkPaint p;
275 p.setStyle(SkPaint::kStroke_Style);
276 p.setStrokeWidth(width);
277 p.getFillPath(path, &fill);
278
279 paint.setColor(WIREFRAME_COLOR);
280 canvas->drawPath(fill, paint);
281 draw_points(canvas, fill, WIREFRAME_COLOR, false);
282 }
283
284 virtual void onDrawContent(SkCanvas* canvas) {
285 SkPath path;
286 SkScalar width = fWidth;
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000287
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000288 path.moveTo(fPts[0]);
289 path.cubicTo(fPts[1], fPts[2], fPts[3]);
290 draw_stroke(canvas, path, width);
291
292 path.reset();
293 path.moveTo(fPts[4]);
294 path.quadTo(fPts[5], fPts[6]);
295 draw_stroke(canvas, path, width);
296
297 SkScalar rad = 32;
298 SkRect r;
299 r.set(&fPts[7], 2);
300 path.reset();
301 SkRRect rr;
302 rr.setRectXY(r, rad, rad);
303 path.addRRect(rr);
304 draw_stroke(canvas, path, width);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000305
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000306 path.reset();
307 SkRRect rr2;
308 rr.inset(width/2, width/2, &rr2);
309 path.addRRect(rr2, SkPath::kCCW_Direction);
310 rr.inset(-width/2, -width/2, &rr2);
311 path.addRRect(rr2, SkPath::kCW_Direction);
312 SkPaint paint;
313 paint.setAntiAlias(true);
314 paint.setColor(0x40FF8844);
315 canvas->drawPath(path, paint);
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000316
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000317 fWidth += fDWidth;
318 if (fDWidth > 0 && fWidth > 100) {
319 fDWidth = -fDWidth;
320 } else if (fDWidth < 0 && fWidth < 10) {
321 fDWidth = -fDWidth;
322 }
323 this->inval(NULL);
324 }
325
326 class MyClick : public Click {
327 public:
328 int fIndex;
329 MyClick(SkView* target, int index) : Click(target), fIndex(index) {}
330 };
331
reed@google.com4d5c26d2013-01-08 16:17:50 +0000332 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
333 unsigned modi) SK_OVERRIDE {
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000334 for (size_t i = 0; i < SK_ARRAY_COUNT(fPts); ++i) {
335 if (hittest(fPts[i], x, y)) {
336 return new MyClick(this, i);
337 }
338 }
reed@google.com4d5c26d2013-01-08 16:17:50 +0000339 return this->INHERITED::onFindClickHandler(x, y, modi);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000340 }
skia.committer@gmail.com21579832012-12-25 02:01:27 +0000341
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000342 virtual bool onClick(Click* click) {
343 int index = ((MyClick*)click)->fIndex;
jvanverth@google.com9c81bd52013-01-03 14:46:41 +0000344 fPts[index].offset(SkIntToScalar(click->fICurr.fX - click->fIPrev.fX),
345 SkIntToScalar(click->fICurr.fY - click->fIPrev.fY));
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000346 this->inval(NULL);
347 return true;
348 }
349
350private:
351 typedef SkView INHERITED;
352};
353
354///////////////////////////////////////////////////////////////////////////////
355
mike@reedtribe.orgb5637092012-12-22 20:53:59 +0000356static SkView* F0() { return new RotateCirclesView; }
357static SkViewRegister gR0(F0);
mike@reedtribe.org61490fa2012-12-24 14:38:46 +0000358static SkView* F1() { return new TestCirclesView; }
359static SkViewRegister gR1(F1);
360static SkView* F2() { return new TestStrokeView; }
361static SkViewRegister gR2(F2);