blob: deb1fb27284f320e1484a0da123a7e3e63a13a04 [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);
reed@google.com1d5aaa82011-05-31 15:35:54 +0000265 delete fFactory;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000266 }
267
268 Draw* setDraw(Draw* d) {
269 SkRefCnt_SafeAssign(fDraw, d);
270 return d;
271 }
272
273 SkColor randColor() {
274 return (SkColor)fRand.nextU() | 0xFF000000;
275 }
276
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000277 Draw* hitTestList(SkScalar x, SkScalar y) const {
278 Draw** first = fList.begin();
279 for (Draw** iter = fList.end(); iter > first;) {
280 --iter;
281 if ((*iter)->hitTest(x, y)) {
282 return *iter;
283 }
284 }
285 return NULL;
286 }
287
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000288protected:
289 // overrides from SkEventSink
290 virtual bool onQuery(SkEvent* evt) {
291 if (SampleCode::TitleQ(*evt)) {
292 SampleCode::TitleR(evt, "Draw");
293 return true;
294 }
295 return this->INHERITED::onQuery(evt);
296 }
297
298 void drawBG(SkCanvas* canvas) {
299 canvas->drawColor(0xFFDDDDDD);
300// canvas->drawColor(SK_ColorWHITE);
301 }
302
303 virtual void onDraw(SkCanvas* canvas) {
304 this->drawBG(canvas);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000305 test_clearonlayers(canvas); return;
306 // test_strokerect(canvas); return;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000307
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000308 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000309 (*iter)->draw(canvas);
310 }
311 if (fDraw) {
312 fDraw->draw(canvas);
313 }
314 }
315
316 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000317 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
318 (*iter)->setSelected(false);
319 }
320
321 Click* c = new Click(this);
322 Draw* d = this->hitTestList(x, y);
323 if (d) {
324 d->setSelected(true);
325 c->setType("dragger");
326 } else {
327 c->setType("maker");
328 }
329 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000330 }
331
332 virtual bool onClick(Click* click) {
333 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000334 if (click->isType("maker")) {
335 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
336 *fList.append() = fDraw;
337 } else {
338 fDraw->unref();
339 }
340 fDraw = NULL;
341 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000342 return true;
343 }
344
345 if (Click::kDown_State == click->fState) {
346 SkPaint p = fFactory->getPaint();
347 p.setColor(this->randColor());
348 fFactory->setPaint(p);
349 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000350
351 if (click->isType("maker")) {
352 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
353 } else if (click->isType("dragger")) {
354 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
355 if ((*iter)->isSelected()) {
356 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
357 click->fCurr.y() - click->fPrev.y());
358 }
359 }
360 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000361 this->inval(NULL);
362 return true;
363 }
364
365private:
366 typedef SkView INHERITED;
367};
368
369//////////////////////////////////////////////////////////////////////////////
370
371static SkView* MyFactory() { return new DrawView; }
372static SkViewRegister reg(MyFactory);
373