blob: 29ad07d200704d0d5d7b399555e0e6f08ae7ebdf [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +00007#include "SampleCode.h"
8#include "SkView.h"
9#include "SkCanvas.h"
10#include "SkGraphics.h"
11#include "SkRandom.h"
12
reed@google.com2f3dc9d2011-05-02 17:33:45 +000013static void test_clearonlayers(SkCanvas* canvas) {
14 SkCanvas& c = *canvas;
rmistry@google.comae933ce2012-08-23 18:19:56 +000015
reed@google.com2f3dc9d2011-05-02 17:33:45 +000016 SkPaint paint;
17 paint.setColor(SK_ColorBLUE);
18 paint.setStyle(SkPaint::kStrokeAndFill_Style);
19 SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
20 c.drawRect(rect, paint);
rmistry@google.comae933ce2012-08-23 18:19:56 +000021
reed@google.com2f3dc9d2011-05-02 17:33:45 +000022 c.clipRect(rect);
rmistry@google.comae933ce2012-08-23 18:19:56 +000023
halcanary96fcdcc2015-08-27 07:41:13 -070024 c.saveLayer(nullptr, nullptr);
reed@google.com2f3dc9d2011-05-02 17:33:45 +000025 rect = SkRect::MakeXYWH(50, 10, 40, 80);
26 c.clipRect(rect, SkRegion::kUnion_Op);
rmistry@google.comae933ce2012-08-23 18:19:56 +000027
reed@google.com2f3dc9d2011-05-02 17:33:45 +000028 rect = SkRect::MakeXYWH(50, 0, 50, 100);
29 // You might draw something here, but it's not necessary.
30 // paint.setColor(SK_ColorRED);
31 // c.drawRect(rect, paint);
32 paint.setXfermodeMode(SkXfermode::kClear_Mode);
33 c.drawRect(rect, paint);
34 c.restore();
35}
36
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000037static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
38 SkPaint p;
rmistry@google.comae933ce2012-08-23 18:19:56 +000039
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000040 p.setAntiAlias(true);
41 p.setStyle(SkPaint::kStroke_Style);
42 p.setStrokeWidth(4);
rmistry@google.comae933ce2012-08-23 18:19:56 +000043
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000044 canvas->drawRect(r, p);
45
46 SkPath path;
47 SkRect r2(r);
48 r2.offset(18, 0);
49 path.addRect(r2);
50
51 canvas->drawPath(path, p);
52}
53
54static void test_strokerect(SkCanvas* canvas) {
55 canvas->drawColor(SK_ColorWHITE);
56
57 SkRect r;
58
59 r.set(10, 10, 14, 14);
reed@google.com261b8e22011-04-14 17:53:24 +000060 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000061 test_strokerect(canvas, r);
62 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000063
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000064 r.set(10, 10, 14.5f, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000065 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000066 test_strokerect(canvas, r);
67 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000068
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000069 r.set(10, 10, 14.5f, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000070 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000071 test_strokerect(canvas, r);
72 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000073
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000074 r.set(10, 10, 20, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000075 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000076 test_strokerect(canvas, r);
77 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000078
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000079 r.set(10, 10, 20, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000080 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000081 test_strokerect(canvas, r);
82 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000083
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000084}
85
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000086class Draw : public SkRefCnt {
87public:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000088 Draw() : fFlags(0) {}
89
90 enum Flags {
91 kSelected_Flag = 1 << 0
92 };
93 int getFlags() const { return fFlags; }
94 void setFlags(int flags);
95
96 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
97 void setSelected(bool pred) {
98 if (pred) {
99 fFlags |= kSelected_Flag;
100 } else {
101 fFlags &= ~kSelected_Flag;
102 }
103 }
104
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000105 void draw(SkCanvas* canvas) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000106 int sc = canvas->save();
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000107 this->onDraw(canvas);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000108 canvas->restoreToCount(sc);
109
110 if (this->isSelected()) {
111 this->drawSelection(canvas);
112 }
113 }
114
115 void drawSelection(SkCanvas* canvas) {
116 int sc = canvas->save();
117 this->onDrawSelection(canvas);
118 canvas->restoreToCount(sc);
119 }
120
121 void getBounds(SkRect* bounds) {
122 this->onGetBounds(bounds);
123 }
124
125 bool hitTest(SkScalar x, SkScalar y) {
126 return this->onHitTest(x, y);
127 }
128
129 void offset(SkScalar dx, SkScalar dy) {
130 if (dx || dy) {
131 this->onOffset(dx, dy);
132 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000133 }
134
135protected:
136 virtual void onDraw(SkCanvas*) = 0;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000137 virtual void onGetBounds(SkRect*) = 0;
138 virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
139 virtual void onDrawSelection(SkCanvas* canvas) {
140 SkRect r;
141 this->getBounds(&r);
142 SkPaint paint;
143 SkPoint pts[4];
144 r.toQuad(pts);
145 paint.setStrokeWidth(SkIntToScalar(10));
146 paint.setColor(0x80FF8844);
147 paint.setStrokeCap(SkPaint::kRound_Cap);
148 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
149 }
150 virtual bool onHitTest(SkScalar x, SkScalar y) {
151 SkRect bounds;
152 this->getBounds(&bounds);
153 return bounds.contains(x, y);
154 }
155
156private:
157 int fFlags;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000158};
159
160class RDraw : public Draw {
161public:
162 enum Style {
163 kRect_Style,
164 kOval_Style,
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000165 kRRect_Style,
166 kFrame_Style
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000167 };
168
169 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
170
171 void setRect(const SkRect& r) {
172 fRect = r;
173 }
174
175 void setPaint(const SkPaint& p) {
176 fPaint = p;
177 }
178
179protected:
180 virtual void onDraw(SkCanvas* canvas) {
181 switch (fStyle) {
182 case kRect_Style:
183 canvas->drawRect(fRect, fPaint);
184 break;
185 case kOval_Style:
186 canvas->drawOval(fRect, fPaint);
187 break;
188 case kRRect_Style: {
189 SkScalar rx = fRect.width() / 5;
190 SkScalar ry = fRect.height() / 5;
191 if (rx < ry) {
192 ry = rx;
193 } else {
194 rx = ry;
195 }
196 canvas->drawRoundRect(fRect, rx, ry, fPaint);
197 break;
198 }
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000199 case kFrame_Style: {
200 SkPath path;
201 path.addOval(fRect, SkPath::kCW_Direction);
202 SkRect r = fRect;
203 r.inset(fRect.width()/6, 0);
204 path.addOval(r, SkPath::kCCW_Direction);
205 canvas->drawPath(path, fPaint);
206 break;
207 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000208 }
209 }
210
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000211 virtual void onGetBounds(SkRect* bounds) {
212 *bounds = fRect;
213 }
214
215 virtual void onOffset(SkScalar dx, SkScalar dy) {
216 fRect.offset(dx, dy);
217 }
218
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000219private:
220 SkRect fRect;
221 SkPaint fPaint;
222 Style fStyle;
223};
224
225class DrawFactory {
226public:
227 DrawFactory() {
228 fPaint.setAntiAlias(true);
229 }
230
231 const SkPaint& getPaint() const { return fPaint; }
232
233 void setPaint(const SkPaint& p) {
234 fPaint = p;
235 }
236
237 virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000238
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000239private:
240 SkPaint fPaint;
241};
242
243class RectFactory : public DrawFactory {
244public:
245 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
246 SkRect r;
247 r.set(p0.x(), p0.y(), p1.x(), p1.y());
248 r.sort();
249
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000250// RDraw* d = new RDraw(r, RDraw::kRRect_Style);
251 RDraw* d = new RDraw(r, RDraw::kFrame_Style);
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000252 d->setPaint(this->getPaint());
253 return d;
254 }
255};
256
257class DrawView : public SkView {
258 Draw* fDraw;
259 DrawFactory* fFactory;
260 SkRandom fRand;
261 SkTDArray<Draw*> fList;
262
263public:
halcanary96fcdcc2015-08-27 07:41:13 -0700264 DrawView() : fDraw(nullptr) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000265 fFactory = new RectFactory;
266 }
267
268 virtual ~DrawView() {
269 fList.unrefAll();
270 SkSafeUnref(fDraw);
reed@google.com1d5aaa82011-05-31 15:35:54 +0000271 delete fFactory;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000272 }
273
274 Draw* setDraw(Draw* d) {
275 SkRefCnt_SafeAssign(fDraw, d);
276 return d;
277 }
278
279 SkColor randColor() {
280 return (SkColor)fRand.nextU() | 0xFF000000;
281 }
282
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000283 Draw* hitTestList(SkScalar x, SkScalar y) const {
284 Draw** first = fList.begin();
285 for (Draw** iter = fList.end(); iter > first;) {
286 --iter;
287 if ((*iter)->hitTest(x, y)) {
288 return *iter;
289 }
290 }
halcanary96fcdcc2015-08-27 07:41:13 -0700291 return nullptr;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000292 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000293
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000294protected:
295 // overrides from SkEventSink
296 virtual bool onQuery(SkEvent* evt) {
297 if (SampleCode::TitleQ(*evt)) {
298 SampleCode::TitleR(evt, "Draw");
299 return true;
300 }
301 return this->INHERITED::onQuery(evt);
302 }
303
304 void drawBG(SkCanvas* canvas) {
305 canvas->drawColor(0xFFDDDDDD);
306// canvas->drawColor(SK_ColorWHITE);
307 }
308
309 virtual void onDraw(SkCanvas* canvas) {
310 this->drawBG(canvas);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000311 test_clearonlayers(canvas); return;
312 // test_strokerect(canvas); return;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000313
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000314 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000315 (*iter)->draw(canvas);
316 }
317 if (fDraw) {
318 fDraw->draw(canvas);
319 }
320 }
321
322 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000323 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
324 (*iter)->setSelected(false);
325 }
326
327 Click* c = new Click(this);
328 Draw* d = this->hitTestList(x, y);
329 if (d) {
330 d->setSelected(true);
331 c->setType("dragger");
332 } else {
333 c->setType("maker");
334 }
335 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000336 }
337
338 virtual bool onClick(Click* click) {
339 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000340 if (click->isType("maker")) {
341 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
342 *fList.append() = fDraw;
343 } else {
344 fDraw->unref();
345 }
halcanary96fcdcc2015-08-27 07:41:13 -0700346 fDraw = nullptr;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000347 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000348 return true;
349 }
350
351 if (Click::kDown_State == click->fState) {
352 SkPaint p = fFactory->getPaint();
353 p.setColor(this->randColor());
354 fFactory->setPaint(p);
355 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000356
357 if (click->isType("maker")) {
358 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
359 } else if (click->isType("dragger")) {
360 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
361 if ((*iter)->isSelected()) {
362 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
363 click->fCurr.y() - click->fPrev.y());
364 }
365 }
366 }
halcanary96fcdcc2015-08-27 07:41:13 -0700367 this->inval(nullptr);
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000368 return true;
369 }
370
371private:
372 typedef SkView INHERITED;
373};
374
375//////////////////////////////////////////////////////////////////////////////
376
377static SkView* MyFactory() { return new DrawView; }
378static SkViewRegister reg(MyFactory);