blob: 616650f9ef969d344a67f7feb91f79753fc70894 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +00008#include "SampleCode.h"
9#include "SkView.h"
10#include "SkCanvas.h"
11#include "SkGraphics.h"
12#include "SkRandom.h"
13
reed@google.com2f3dc9d2011-05-02 17:33:45 +000014static void test_clearonlayers(SkCanvas* canvas) {
15 SkCanvas& c = *canvas;
rmistry@google.comae933ce2012-08-23 18:19:56 +000016
reed@google.com2f3dc9d2011-05-02 17:33:45 +000017 SkPaint paint;
18 paint.setColor(SK_ColorBLUE);
19 paint.setStyle(SkPaint::kStrokeAndFill_Style);
20 SkRect rect = SkRect::MakeXYWH(25, 25, 50, 50);
21 c.drawRect(rect, paint);
rmistry@google.comae933ce2012-08-23 18:19:56 +000022
reed@google.com2f3dc9d2011-05-02 17:33:45 +000023 c.clipRect(rect);
rmistry@google.comae933ce2012-08-23 18:19:56 +000024
reed@google.com2f3dc9d2011-05-02 17:33:45 +000025 c.saveLayer(NULL, NULL);
26 rect = SkRect::MakeXYWH(50, 10, 40, 80);
27 c.clipRect(rect, SkRegion::kUnion_Op);
rmistry@google.comae933ce2012-08-23 18:19:56 +000028
reed@google.com2f3dc9d2011-05-02 17:33:45 +000029 rect = SkRect::MakeXYWH(50, 0, 50, 100);
30 // You might draw something here, but it's not necessary.
31 // paint.setColor(SK_ColorRED);
32 // c.drawRect(rect, paint);
33 paint.setXfermodeMode(SkXfermode::kClear_Mode);
34 c.drawRect(rect, paint);
35 c.restore();
36}
37
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000038static void test_strokerect(SkCanvas* canvas, const SkRect& r) {
39 SkPaint p;
rmistry@google.comae933ce2012-08-23 18:19:56 +000040
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000041 p.setAntiAlias(true);
42 p.setStyle(SkPaint::kStroke_Style);
43 p.setStrokeWidth(4);
rmistry@google.comae933ce2012-08-23 18:19:56 +000044
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000045 canvas->drawRect(r, p);
46
47 SkPath path;
48 SkRect r2(r);
49 r2.offset(18, 0);
50 path.addRect(r2);
51
52 canvas->drawPath(path, p);
53}
54
55static void test_strokerect(SkCanvas* canvas) {
56 canvas->drawColor(SK_ColorWHITE);
57
58 SkRect r;
59
60 r.set(10, 10, 14, 14);
reed@google.com261b8e22011-04-14 17:53:24 +000061 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000062 test_strokerect(canvas, r);
63 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000064
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000065 r.set(10, 10, 14.5f, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000066 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000067 test_strokerect(canvas, r);
68 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000069
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000070 r.set(10, 10, 14.5f, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000071 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000072 test_strokerect(canvas, r);
73 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000074
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000075 r.set(10, 10, 20, 14.5f);
reed@google.com261b8e22011-04-14 17:53:24 +000076 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000077 test_strokerect(canvas, r);
78 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000079
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000080 r.set(10, 10, 20, 20);
reed@google.com261b8e22011-04-14 17:53:24 +000081 r.offset(0.25f, 0.3333f);
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000082 test_strokerect(canvas, r);
83 canvas->translate(0, 20);
rmistry@google.comae933ce2012-08-23 18:19:56 +000084
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +000085}
86
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +000087class Draw : public SkRefCnt {
88public:
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +000089 Draw() : fFlags(0) {}
90
91 enum Flags {
92 kSelected_Flag = 1 << 0
93 };
94 int getFlags() const { return fFlags; }
95 void setFlags(int flags);
96
97 bool isSelected() const { return SkToBool(fFlags & kSelected_Flag); }
98 void setSelected(bool pred) {
99 if (pred) {
100 fFlags |= kSelected_Flag;
101 } else {
102 fFlags &= ~kSelected_Flag;
103 }
104 }
105
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000106 void draw(SkCanvas* canvas) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000107 int sc = canvas->save();
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000108 this->onDraw(canvas);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000109 canvas->restoreToCount(sc);
110
111 if (this->isSelected()) {
112 this->drawSelection(canvas);
113 }
114 }
115
116 void drawSelection(SkCanvas* canvas) {
117 int sc = canvas->save();
118 this->onDrawSelection(canvas);
119 canvas->restoreToCount(sc);
120 }
121
122 void getBounds(SkRect* bounds) {
123 this->onGetBounds(bounds);
124 }
125
126 bool hitTest(SkScalar x, SkScalar y) {
127 return this->onHitTest(x, y);
128 }
129
130 void offset(SkScalar dx, SkScalar dy) {
131 if (dx || dy) {
132 this->onOffset(dx, dy);
133 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000134 }
135
136protected:
137 virtual void onDraw(SkCanvas*) = 0;
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000138 virtual void onGetBounds(SkRect*) = 0;
139 virtual void onOffset(SkScalar dx, SkScalar dy) = 0;
140 virtual void onDrawSelection(SkCanvas* canvas) {
141 SkRect r;
142 this->getBounds(&r);
143 SkPaint paint;
144 SkPoint pts[4];
145 r.toQuad(pts);
146 paint.setStrokeWidth(SkIntToScalar(10));
147 paint.setColor(0x80FF8844);
148 paint.setStrokeCap(SkPaint::kRound_Cap);
149 canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, pts, paint);
150 }
151 virtual bool onHitTest(SkScalar x, SkScalar y) {
152 SkRect bounds;
153 this->getBounds(&bounds);
154 return bounds.contains(x, y);
155 }
156
157private:
158 int fFlags;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000159};
160
161class RDraw : public Draw {
162public:
163 enum Style {
164 kRect_Style,
165 kOval_Style,
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000166 kRRect_Style,
167 kFrame_Style
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000168 };
169
170 RDraw(const SkRect& r, Style s) : fRect(r), fStyle(s) {}
171
172 void setRect(const SkRect& r) {
173 fRect = r;
174 }
175
176 void setPaint(const SkPaint& p) {
177 fPaint = p;
178 }
179
180protected:
181 virtual void onDraw(SkCanvas* canvas) {
182 switch (fStyle) {
183 case kRect_Style:
184 canvas->drawRect(fRect, fPaint);
185 break;
186 case kOval_Style:
187 canvas->drawOval(fRect, fPaint);
188 break;
189 case kRRect_Style: {
190 SkScalar rx = fRect.width() / 5;
191 SkScalar ry = fRect.height() / 5;
192 if (rx < ry) {
193 ry = rx;
194 } else {
195 rx = ry;
196 }
197 canvas->drawRoundRect(fRect, rx, ry, fPaint);
198 break;
199 }
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000200 case kFrame_Style: {
201 SkPath path;
202 path.addOval(fRect, SkPath::kCW_Direction);
203 SkRect r = fRect;
204 r.inset(fRect.width()/6, 0);
205 path.addOval(r, SkPath::kCCW_Direction);
206 canvas->drawPath(path, fPaint);
207 break;
208 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000209 }
210 }
211
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000212 virtual void onGetBounds(SkRect* bounds) {
213 *bounds = fRect;
214 }
215
216 virtual void onOffset(SkScalar dx, SkScalar dy) {
217 fRect.offset(dx, dy);
218 }
219
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000220private:
221 SkRect fRect;
222 SkPaint fPaint;
223 Style fStyle;
224};
225
226class DrawFactory {
227public:
228 DrawFactory() {
229 fPaint.setAntiAlias(true);
230 }
231
232 const SkPaint& getPaint() const { return fPaint; }
233
234 void setPaint(const SkPaint& p) {
235 fPaint = p;
236 }
237
238 virtual Draw* create(const SkPoint&, const SkPoint&) = 0;
rmistry@google.comae933ce2012-08-23 18:19:56 +0000239
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000240private:
241 SkPaint fPaint;
242};
243
244class RectFactory : public DrawFactory {
245public:
246 virtual Draw* create(const SkPoint& p0, const SkPoint& p1) {
247 SkRect r;
248 r.set(p0.x(), p0.y(), p1.x(), p1.y());
249 r.sort();
250
mike@reedtribe.orga8282ef2011-04-14 01:22:45 +0000251// RDraw* d = new RDraw(r, RDraw::kRRect_Style);
252 RDraw* d = new RDraw(r, RDraw::kFrame_Style);
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000253 d->setPaint(this->getPaint());
254 return d;
255 }
256};
257
258class DrawView : public SkView {
259 Draw* fDraw;
260 DrawFactory* fFactory;
261 SkRandom fRand;
262 SkTDArray<Draw*> fList;
263
264public:
265 DrawView() : fDraw(NULL) {
266 fFactory = new RectFactory;
267 }
268
269 virtual ~DrawView() {
270 fList.unrefAll();
271 SkSafeUnref(fDraw);
reed@google.com1d5aaa82011-05-31 15:35:54 +0000272 delete fFactory;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000273 }
274
275 Draw* setDraw(Draw* d) {
276 SkRefCnt_SafeAssign(fDraw, d);
277 return d;
278 }
279
280 SkColor randColor() {
281 return (SkColor)fRand.nextU() | 0xFF000000;
282 }
283
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000284 Draw* hitTestList(SkScalar x, SkScalar y) const {
285 Draw** first = fList.begin();
286 for (Draw** iter = fList.end(); iter > first;) {
287 --iter;
288 if ((*iter)->hitTest(x, y)) {
289 return *iter;
290 }
291 }
292 return NULL;
293 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000294
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000295protected:
296 // overrides from SkEventSink
297 virtual bool onQuery(SkEvent* evt) {
298 if (SampleCode::TitleQ(*evt)) {
299 SampleCode::TitleR(evt, "Draw");
300 return true;
301 }
302 return this->INHERITED::onQuery(evt);
303 }
304
305 void drawBG(SkCanvas* canvas) {
306 canvas->drawColor(0xFFDDDDDD);
307// canvas->drawColor(SK_ColorWHITE);
308 }
309
310 virtual void onDraw(SkCanvas* canvas) {
311 this->drawBG(canvas);
reed@google.com2f3dc9d2011-05-02 17:33:45 +0000312 test_clearonlayers(canvas); return;
313 // test_strokerect(canvas); return;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000314
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000315 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000316 (*iter)->draw(canvas);
317 }
318 if (fDraw) {
319 fDraw->draw(canvas);
320 }
321 }
322
323 virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000324 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
325 (*iter)->setSelected(false);
326 }
327
328 Click* c = new Click(this);
329 Draw* d = this->hitTestList(x, y);
330 if (d) {
331 d->setSelected(true);
332 c->setType("dragger");
333 } else {
334 c->setType("maker");
335 }
336 return c;
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000337 }
338
339 virtual bool onClick(Click* click) {
340 if (Click::kUp_State == click->fState) {
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000341 if (click->isType("maker")) {
342 if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) {
343 *fList.append() = fDraw;
344 } else {
345 fDraw->unref();
346 }
347 fDraw = NULL;
348 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000349 return true;
350 }
351
352 if (Click::kDown_State == click->fState) {
353 SkPaint p = fFactory->getPaint();
354 p.setColor(this->randColor());
355 fFactory->setPaint(p);
356 }
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000357
358 if (click->isType("maker")) {
359 this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref();
360 } else if (click->isType("dragger")) {
361 for (Draw** iter = fList.begin(); iter < fList.end(); iter++) {
362 if ((*iter)->isSelected()) {
363 (*iter)->offset(click->fCurr.x() - click->fPrev.x(),
364 click->fCurr.y() - click->fPrev.y());
365 }
366 }
367 }
mike@reedtribe.orgb7d956d2011-03-20 20:19:16 +0000368 this->inval(NULL);
369 return true;
370 }
371
372private:
373 typedef SkView INHERITED;
374};
375
376//////////////////////////////////////////////////////////////////////////////
377
378static SkView* MyFactory() { return new DrawView; }
379static SkViewRegister reg(MyFactory);