blob: 54070d1f33c3707a68952144c744c03281f94cf9 [file] [log] [blame]
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGraphics.h"
5#include "SkRandom.h"
6
reed@google.com2f3dc9d2011-05-02 17:33:45 +00007static void test_clearonlayers(SkCanvas* canvas) {
8 SkCanvas& c = *canvas;
9
10 SkPaint paint;
11 paint.setColor(SK_ColorBLUE);
12 paint.setStyle(SkPaint::kStrokeAndFill_Style);
13 SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
14 c.drawRect(rect, paint);
15
16 c.clipRect(rect);
17
18 c.saveLayer(NULL, NULL);
19 rect = SkRect::MakeXYWH(50, 10, 40, 80);
20 c.clipRect(rect, SkRegion::kUnion_Op);
21
22 rect = SkRect::MakeXYWH(50, 0, 50, 100);
23 // You might draw something here, but it's not necessary.
24 // paint.setColor(SK_ColorRED);
25 // c.drawRect(rect, paint);
26 paint.setXfermodeMode(SkXfermode::kClear_Mode);
27 c.drawRect(rect, paint);
28 c.restore();
29}
30
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000031static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
32 SkPaint p;
33
34 p.setAntiAlias(true);
35 p.setStyle(SkPaint::kStroke_Style);
36 p.setStrokeWidth(4);
37
38 canvas->drawRect(r, p);
39
40 SkPath path;
41 SkRect r2(r);
42 r2.offset(18, 0);
43 path.addRect(r2);
44
45 canvas->drawPath(path, p);
46}
47
48static void test_strokerect(SkCanvas* canvas) {
49 canvas->drawColor(SK_ColorWHITE);
50
51 SkRect r;
52
53 r.set(10, 10, 14, 14);
reed@google.com261b8e22011-04-14 17:53:24 +000054 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000055 test_strokerect(canvas, r);
56 canvas->translate(0, 20);
57
58 r.set(10, 10, 14.5f, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000059 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000060 test_strokerect(canvas, r);
61 canvas->translate(0, 20);
62
63 r.set(10, 10, 14.5f, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000064 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000065 test_strokerect(canvas, r);
66 canvas->translate(0, 20);
67
68 r.set(10, 10, 20, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000069 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000070 test_strokerect(canvas, r);
71 canvas->translate(0, 20);
72
73 r.set(10, 10, 20, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000074 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000075 test_strokerect(canvas, r);
76 canvas->translate(0, 20);
77
78}
79
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000080class Draw : public SkRefCnt {
81public:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000082 Draw() : fFlags(0) {}
83
84 enum Flags {
85 kSelected_Flag = 1 << 0
86 };
87 int getFlags() const { return fFlags; }
88 void setFlags(int flags);
89
90 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
91 void setSelected(bool pred) {
92 if (pred) {
93 fFlags |= kSelected_Flag;
94 } else {
95 fFlags &= ~kSelected_Flag;
96 }
97 }
98
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000099 void draw(SkCanvas* canvas) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000100 int sc = canvas->save();
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000101 this->onDraw(canvas);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000102 canvas->restoreToCount(sc);
103
104 if (this->isSelected()) {
105 this->drawSelection(canvas);
106 }
107 }
108
109 void drawSelection(SkCanvas* canvas) {
110 int sc = canvas->save();
111 this->onDrawSelection(canvas);
112 canvas->restoreToCount(sc);
113 }
114
115 void getBounds(SkRect* bounds) {
116 this->onGetBounds(bounds);
117 }
118
119 bool hitTest(SkScalar x, SkScalar y) {
120 return this->onHitTest(x, y);
121 }
122
123 void offset(SkScalar dx, SkScalar dy) {
124 if (dx || dy) {
125 this->onOffset(dx, dy);
126 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000127 }
128
129protected:
130 virtual void onDraw(SkCanvas*) = 0;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000131 virtual void onGetBounds(SkRect*) = 0;
132 virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
133 virtual void onDrawSelection(SkCanvas* canvas) {
134 SkRect r;
135 this->getBounds(&r);
136 SkPaint paint;
137 SkPoint pts[4];
138 r.toQuad(pts);
139 paint.setStrokeWidth(SkIntToScalar(10));
140 paint.setColor(0x80FF8844);
141 paint.setStrokeCap(SkPaint::kRound_Cap);
142 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
143 }
144 virtual bool onHitTest(SkScalar x, SkScalar y) {
145 SkRect bounds;
146 this->getBounds(&bounds);
147 return bounds.contains(x, y);
148 }
149
150private:
151 int fFlags;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000152};
153
154class RDraw : public Draw {
155public:
156 enum Style {
157 kRect_Style,
158 kOval_Style,
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000159 kRRect_Style,
160 kFrame_Style
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000161 };
162
163 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
164
165 void setRect(const SkRect& r) {
166 fRect = r;
167 }
168
169 void setPaint(const SkPaint& p) {
170 fPaint = p;
171 }
172
173protected:
174 virtual void onDraw(SkCanvas* canvas) {
175 switch (fStyle) {
176 case kRect_Style:
177 canvas->drawRect(fRect, fPaint);
178 break;
179 case kOval_Style:
180 canvas->drawOval(fRect, fPaint);
181 break;
182 case kRRect_Style: {
183 SkScalar rx = fRect.width() / 5;
184 SkScalar ry = fRect.height() / 5;
185 if (rx < ry) {
186 ry = rx;
187 } else {
188 rx = ry;
189 }
190 canvas->drawRoundRect(fRect, rx, ry, fPaint);
191 break;
192 }
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000193 case kFrame_Style: {
194 SkPath path;
195 path.addOval(fRect, SkPath::kCW_Direction);
196 SkRect r = fRect;
197 r.inset(fRect.width()/6, 0);
198 path.addOval(r, SkPath::kCCW_Direction);
199 canvas->drawPath(path, fPaint);
200 break;
201 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000202 }
203 }
204
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000205 virtual void onGetBounds(SkRect* bounds) {
206 *bounds = fRect;
207 }
208
209 virtual void onOffset(SkScalar dx, SkScalar dy) {
210 fRect.offset(dx, dy);
211 }
212
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000213private:
214 SkRect fRect;
215 SkPaint fPaint;
216 Style fStyle;
217};
218
219class DrawFactory {
220public:
221 DrawFactory() {
222 fPaint.setAntiAlias(true);
223 }
224
225 const SkPaint& getPaint() const { return fPaint; }
226
227 void setPaint(const SkPaint& p) {
228 fPaint = p;
229 }
230
231 virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
232
233private:
234 SkPaint fPaint;
235};
236
237class RectFactory : public DrawFactory {
238public:
239 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
240 SkRect r;
241 r.set(p0.x(), p0.y(), p1.x(), p1.y());
242 r.sort();
243
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000244// RDraw* d = new RDraw(r, RDraw::kRRect_Style);
245 RDraw* d = new RDraw(r, RDraw::kFrame_Style);
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000246 d->setPaint(this->getPaint());
247 return d;
248 }
249};
250
251class DrawView : public SkView {
252 Draw* fDraw;
253 DrawFactory* fFactory;
254 SkRandom fRand;
255 SkTDArray<Draw*> fList;
256
257public:
258 DrawView() : fDraw(NULL) {
259 fFactory = new RectFactory;
260 }
261
262 virtual ~DrawView() {
263 fList.unrefAll();
264 SkSafeUnref(fDraw);
265 }
266
267 Draw* setDraw(Draw* d) {
268 SkRefCnt_SafeAssign(fDraw, d);
269 return d;
270 }
271
272 SkColor randColor() {
273 return (SkColor)fRand.nextU() | 0xFF000000;
274 }
275
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000276 Draw* hitTestList(SkScalar x, SkScalar y) const {
277 Draw** first = fList.begin();
278 for (Draw** iter = fList.end(); iter > first;) {
279 --iter;
280 if ((*iter)->hitTest(x, y)) {
281 return *iter;
282 }
283 }
284 return NULL;
285 }
286
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000287protected:
288 // overrides from SkEventSink
289 virtual bool onQuery(SkEvent* evt) {
290 if (SampleCode::TitleQ(*evt)) {
291 SampleCode::TitleR(evt, "Draw");
292 return true;
293 }
294 return this->INHERITED::onQuery(evt);
295 }
296
297 void drawBG(SkCanvas* canvas) {
298 canvas->drawColor(0xFFDDDDDD);
299// canvas->drawColor(SK_ColorWHITE);
300 }
301
302 virtual void onDraw(SkCanvas* canvas) {
303 this->drawBG(canvas);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000304 test_clearonlayers(canvas); return;
305 // test_strokerect(canvas); return;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000306
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000307 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000308 (*iter)->draw(canvas);
309 }
310 if (fDraw) {
311 fDraw->draw(canvas);
312 }
313 }
314
315 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000316 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
317 (*iter)->setSelected(false);
318 }
319
320 Click* c = new Click(this);
321 Draw* d = this->hitTestList(x, y);
322 if (d) {
323 d->setSelected(true);
324 c->setType("dragger");
325 } else {
326 c->setType("maker");
327 }
328 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000329 }
330
331 virtual bool onClick(Click* click) {
332 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000333 if (click->isType("maker")) {
334 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
335 *fList.append() = fDraw;
336 } else {
337 fDraw->unref();
338 }
339 fDraw = NULL;
340 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000341 return true;
342 }
343
344 if (Click::kDown_State == click->fState) {
345 SkPaint p = fFactory->getPaint();
346 p.setColor(this->randColor());
347 fFactory->setPaint(p);
348 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000349
350 if (click->isType("maker")) {
351 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
352 } else if (click->isType("dragger")) {
353 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
354 if ((*iter)->isSelected()) {
355 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
356 click->fCurr.y() - click->fPrev.y());
357 }
358 }
359 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000360 this->inval(NULL);
361 return true;
362 }
363
364private:
365 typedef SkView INHERITED;
366};
367
368//////////////////////////////////////////////////////////////////////////////
369
370static SkView* MyFactory() { return new DrawView; }
371static SkViewRegister reg(MyFactory);
372